Skip to content

Commit 481b1de

Browse files
Add reusable ui components
1 parent 968bbb5 commit 481b1de

File tree

5 files changed

+209
-0
lines changed

5 files changed

+209
-0
lines changed

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/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 }

components/ui/label.tsx

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import * as LabelPrimitive from "@radix-ui/react-label"
5+
import { cva, type VariantProps } from "class-variance-authority"
6+
7+
import { cn } from "@/lib/utils"
8+
9+
const labelVariants = cva(
10+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
11+
)
12+
13+
const Label = React.forwardRef<
14+
React.ElementRef<typeof LabelPrimitive.Root>,
15+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
16+
VariantProps<typeof labelVariants>
17+
>(({ className, ...props }, ref) => (
18+
<LabelPrimitive.Root
19+
ref={ref}
20+
className={cn(labelVariants(), className)}
21+
{...props}
22+
/>
23+
))
24+
Label.displayName = LabelPrimitive.Root.displayName
25+
26+
export { Label }

components/ui/slider.tsx

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import * as SliderPrimitive from "@radix-ui/react-slider"
5+
6+
import { cn } from "@/lib/utils"
7+
8+
const Slider = React.forwardRef<
9+
React.ElementRef<typeof SliderPrimitive.Root>,
10+
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
11+
>(({ className, ...props }, ref) => (
12+
<SliderPrimitive.Root
13+
ref={ref}
14+
className={cn(
15+
"relative flex w-full touch-none select-none items-center",
16+
className
17+
)}
18+
{...props}
19+
>
20+
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
21+
<SliderPrimitive.Range className="absolute h-full bg-primary" />
22+
</SliderPrimitive.Track>
23+
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
24+
</SliderPrimitive.Root>
25+
))
26+
Slider.displayName = SliderPrimitive.Root.displayName
27+
28+
export { Slider }

0 commit comments

Comments
 (0)