Skip to content

Commit 055f1a1

Browse files
Adding Shadcn UI component
1 parent fda6ec6 commit 055f1a1

File tree

7 files changed

+542
-0
lines changed

7 files changed

+542
-0
lines changed

components/ui/badge.tsx

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as React from "react"
2+
import { cva, type VariantProps } from "class-variance-authority"
3+
4+
import { cn } from "lib/utils"
5+
6+
const badgeVariants = cva(
7+
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8+
{
9+
variants: {
10+
variant: {
11+
default:
12+
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
13+
secondary:
14+
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15+
destructive:
16+
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
17+
outline: "text-foreground",
18+
},
19+
},
20+
defaultVariants: {
21+
variant: "default",
22+
},
23+
}
24+
)
25+
26+
export interface BadgeProps
27+
extends React.HTMLAttributes<HTMLDivElement>,
28+
VariantProps<typeof badgeVariants> {}
29+
30+
function Badge({ className, variant, ...props }: BadgeProps) {
31+
return (
32+
<div className={cn(badgeVariants({ variant }), className)} {...props} />
33+
)
34+
}
35+
36+
export { Badge, badgeVariants }

components/ui/button.tsx

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { cva, type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "lib/utils"
6+
7+
const buttonVariants = cva(
8+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
9+
{
10+
variants: {
11+
variant: {
12+
default:
13+
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
14+
destructive:
15+
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
16+
outline:
17+
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
18+
secondary:
19+
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
20+
ghost: "hover:bg-accent hover:text-accent-foreground",
21+
link: "text-primary underline-offset-4 hover:underline",
22+
},
23+
size: {
24+
default: "h-9 px-4 py-2",
25+
sm: "h-8 rounded-md px-3 text-xs",
26+
lg: "h-10 rounded-md px-8",
27+
icon: "h-9 w-9",
28+
},
29+
},
30+
defaultVariants: {
31+
variant: "default",
32+
size: "default",
33+
},
34+
}
35+
)
36+
37+
export interface ButtonProps
38+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
39+
VariantProps<typeof buttonVariants> {
40+
asChild?: boolean
41+
}
42+
43+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
44+
({ className, variant, size, asChild = false, ...props }, ref) => {
45+
const Comp = asChild ? Slot : "button"
46+
return (
47+
<Comp
48+
className={cn(buttonVariants({ variant, size, className }))}
49+
ref={ref}
50+
{...props}
51+
/>
52+
)
53+
}
54+
)
55+
Button.displayName = "Button"
56+
57+
export { Button, buttonVariants }

components/ui/card.tsx

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import * as React from "react"
2+
3+
import { cn } from "lib/utils"
4+
5+
const Card = React.forwardRef<
6+
HTMLDivElement,
7+
React.HTMLAttributes<HTMLDivElement>
8+
>(({ className, ...props }, ref) => (
9+
<div
10+
ref={ref}
11+
className={cn(
12+
"rounded-xl border bg-card text-card-foreground shadow",
13+
className
14+
)}
15+
{...props}
16+
/>
17+
))
18+
Card.displayName = "Card"
19+
20+
const CardHeader = React.forwardRef<
21+
HTMLDivElement,
22+
React.HTMLAttributes<HTMLDivElement>
23+
>(({ className, ...props }, ref) => (
24+
<div
25+
ref={ref}
26+
className={cn("flex flex-col space-y-1.5 p-6", className)}
27+
{...props}
28+
/>
29+
))
30+
CardHeader.displayName = "CardHeader"
31+
32+
const CardTitle = React.forwardRef<
33+
HTMLDivElement,
34+
React.HTMLAttributes<HTMLDivElement>
35+
>(({ className, ...props }, ref) => (
36+
<div
37+
ref={ref}
38+
className={cn("font-semibold leading-none tracking-tight", className)}
39+
{...props}
40+
/>
41+
))
42+
CardTitle.displayName = "CardTitle"
43+
44+
const CardDescription = React.forwardRef<
45+
HTMLDivElement,
46+
React.HTMLAttributes<HTMLDivElement>
47+
>(({ className, ...props }, ref) => (
48+
<div
49+
ref={ref}
50+
className={cn("text-sm text-muted-foreground", className)}
51+
{...props}
52+
/>
53+
))
54+
CardDescription.displayName = "CardDescription"
55+
56+
const CardContent = React.forwardRef<
57+
HTMLDivElement,
58+
React.HTMLAttributes<HTMLDivElement>
59+
>(({ className, ...props }, ref) => (
60+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
61+
))
62+
CardContent.displayName = "CardContent"
63+
64+
const CardFooter = React.forwardRef<
65+
HTMLDivElement,
66+
React.HTMLAttributes<HTMLDivElement>
67+
>(({ className, ...props }, ref) => (
68+
<div
69+
ref={ref}
70+
className={cn("flex items-center p-6 pt-0", className)}
71+
{...props}
72+
/>
73+
))
74+
CardFooter.displayName = "CardFooter"
75+
76+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }

components/ui/dropdown-menu.tsx

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import * as React from "react"
2+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
3+
import { Check, ChevronRight, Circle } from "lucide-react"
4+
5+
import { cn } from "lib/utils"
6+
7+
const DropdownMenu = DropdownMenuPrimitive.Root
8+
9+
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
10+
11+
const DropdownMenuGroup = DropdownMenuPrimitive.Group
12+
13+
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
14+
15+
const DropdownMenuSub = DropdownMenuPrimitive.Sub
16+
17+
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
18+
19+
const DropdownMenuSubTrigger = React.forwardRef<
20+
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
21+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
22+
inset?: boolean
23+
}
24+
>(({ className, inset, children, ...props }, ref) => (
25+
<DropdownMenuPrimitive.SubTrigger
26+
ref={ref}
27+
className={cn(
28+
"flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
29+
inset && "pl-8",
30+
className
31+
)}
32+
{...props}
33+
>
34+
{children}
35+
<ChevronRight className="ml-auto" />
36+
</DropdownMenuPrimitive.SubTrigger>
37+
))
38+
DropdownMenuSubTrigger.displayName =
39+
DropdownMenuPrimitive.SubTrigger.displayName
40+
41+
const DropdownMenuSubContent = React.forwardRef<
42+
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
43+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
44+
>(({ className, ...props }, ref) => (
45+
<DropdownMenuPrimitive.SubContent
46+
ref={ref}
47+
className={cn(
48+
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
49+
className
50+
)}
51+
{...props}
52+
/>
53+
))
54+
DropdownMenuSubContent.displayName =
55+
DropdownMenuPrimitive.SubContent.displayName
56+
57+
const DropdownMenuContent = React.forwardRef<
58+
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
59+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
60+
>(({ className, sideOffset = 4, ...props }, ref) => (
61+
<DropdownMenuPrimitive.Portal>
62+
<DropdownMenuPrimitive.Content
63+
ref={ref}
64+
sideOffset={sideOffset}
65+
className={cn(
66+
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
67+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
68+
className
69+
)}
70+
{...props}
71+
/>
72+
</DropdownMenuPrimitive.Portal>
73+
))
74+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
75+
76+
const DropdownMenuItem = React.forwardRef<
77+
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
78+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
79+
inset?: boolean
80+
}
81+
>(({ className, inset, ...props }, ref) => (
82+
<DropdownMenuPrimitive.Item
83+
ref={ref}
84+
className={cn(
85+
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
86+
inset && "pl-8",
87+
className
88+
)}
89+
{...props}
90+
/>
91+
))
92+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
93+
94+
const DropdownMenuCheckboxItem = React.forwardRef<
95+
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
96+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
97+
>(({ className, children, checked, ...props }, ref) => (
98+
<DropdownMenuPrimitive.CheckboxItem
99+
ref={ref}
100+
className={cn(
101+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
102+
className
103+
)}
104+
checked={checked}
105+
{...props}
106+
>
107+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
108+
<DropdownMenuPrimitive.ItemIndicator>
109+
<Check className="h-4 w-4" />
110+
</DropdownMenuPrimitive.ItemIndicator>
111+
</span>
112+
{children}
113+
</DropdownMenuPrimitive.CheckboxItem>
114+
))
115+
DropdownMenuCheckboxItem.displayName =
116+
DropdownMenuPrimitive.CheckboxItem.displayName
117+
118+
const DropdownMenuRadioItem = React.forwardRef<
119+
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
120+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
121+
>(({ className, children, ...props }, ref) => (
122+
<DropdownMenuPrimitive.RadioItem
123+
ref={ref}
124+
className={cn(
125+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
126+
className
127+
)}
128+
{...props}
129+
>
130+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
131+
<DropdownMenuPrimitive.ItemIndicator>
132+
<Circle className="h-2 w-2 fill-current" />
133+
</DropdownMenuPrimitive.ItemIndicator>
134+
</span>
135+
{children}
136+
</DropdownMenuPrimitive.RadioItem>
137+
))
138+
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
139+
140+
const DropdownMenuLabel = React.forwardRef<
141+
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
142+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
143+
inset?: boolean
144+
}
145+
>(({ className, inset, ...props }, ref) => (
146+
<DropdownMenuPrimitive.Label
147+
ref={ref}
148+
className={cn(
149+
"px-2 py-1.5 text-sm font-semibold",
150+
inset && "pl-8",
151+
className
152+
)}
153+
{...props}
154+
/>
155+
))
156+
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
157+
158+
const DropdownMenuSeparator = React.forwardRef<
159+
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
160+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
161+
>(({ className, ...props }, ref) => (
162+
<DropdownMenuPrimitive.Separator
163+
ref={ref}
164+
className={cn("-mx-1 my-1 h-px bg-muted", className)}
165+
{...props}
166+
/>
167+
))
168+
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
169+
170+
const DropdownMenuShortcut = ({
171+
className,
172+
...props
173+
}: React.HTMLAttributes<HTMLSpanElement>) => {
174+
return (
175+
<span
176+
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
177+
{...props}
178+
/>
179+
)
180+
}
181+
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
182+
183+
export {
184+
DropdownMenu,
185+
DropdownMenuTrigger,
186+
DropdownMenuContent,
187+
DropdownMenuItem,
188+
DropdownMenuCheckboxItem,
189+
DropdownMenuRadioItem,
190+
DropdownMenuLabel,
191+
DropdownMenuSeparator,
192+
DropdownMenuShortcut,
193+
DropdownMenuGroup,
194+
DropdownMenuPortal,
195+
DropdownMenuSub,
196+
DropdownMenuSubContent,
197+
DropdownMenuSubTrigger,
198+
DropdownMenuRadioGroup,
199+
}

components/ui/input.tsx

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as React from "react"
2+
3+
import { cn } from "lib/utils"
4+
5+
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
6+
({ className, type, ...props }, ref) => {
7+
return (
8+
<input
9+
type={type}
10+
className={cn(
11+
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
12+
className
13+
)}
14+
ref={ref}
15+
{...props}
16+
/>
17+
)
18+
}
19+
)
20+
Input.displayName = "Input"
21+
22+
export { Input }

0 commit comments

Comments
 (0)