Skip to content

Commit d78b5e9

Browse files
committed
Add shadcn components
1 parent 2672075 commit d78b5e9

File tree

8 files changed

+750
-0
lines changed

8 files changed

+750
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import * as AvatarPrimitive from "@radix-ui/react-avatar"
5+
6+
import { cn } from "@/lib/utils"
7+
8+
const Avatar = React.forwardRef<
9+
React.ElementRef<typeof AvatarPrimitive.Root>,
10+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
11+
>(({ className, ...props }, ref) => (
12+
<AvatarPrimitive.Root
13+
ref={ref}
14+
className={cn(
15+
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
16+
className
17+
)}
18+
{...props}
19+
/>
20+
))
21+
Avatar.displayName = AvatarPrimitive.Root.displayName
22+
23+
const AvatarImage = React.forwardRef<
24+
React.ElementRef<typeof AvatarPrimitive.Image>,
25+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
26+
>(({ className, ...props }, ref) => (
27+
<AvatarPrimitive.Image
28+
ref={ref}
29+
className={cn("aspect-square h-full w-full", className)}
30+
{...props}
31+
/>
32+
))
33+
AvatarImage.displayName = AvatarPrimitive.Image.displayName
34+
35+
const AvatarFallback = React.forwardRef<
36+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
37+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
38+
>(({ className, ...props }, ref) => (
39+
<AvatarPrimitive.Fallback
40+
ref={ref}
41+
className={cn(
42+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
43+
className
44+
)}
45+
{...props}
46+
/>
47+
))
48+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
49+
50+
export { Avatar, AvatarImage, AvatarFallback }
Lines changed: 57 additions & 0 deletions
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 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",
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 }
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import { ChevronLeftIcon, ChevronRightIcon } from "@radix-ui/react-icons"
5+
import { DayPicker } from "react-day-picker"
6+
7+
import { cn } from "@/lib/utils"
8+
import { buttonVariants } from "@/components/ui/button"
9+
10+
export type CalendarProps = React.ComponentProps<typeof DayPicker>
11+
12+
function Calendar({
13+
className,
14+
classNames,
15+
showOutsideDays = true,
16+
...props
17+
}: CalendarProps) {
18+
return (
19+
<DayPicker
20+
showOutsideDays={showOutsideDays}
21+
className={cn("p-3", className)}
22+
classNames={{
23+
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
24+
month: "space-y-4",
25+
caption: "flex justify-center pt-1 relative items-center",
26+
caption_label: "text-sm font-medium",
27+
nav: "space-x-1 flex items-center",
28+
nav_button: cn(
29+
buttonVariants({ variant: "outline" }),
30+
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
31+
),
32+
nav_button_previous: "absolute left-1",
33+
nav_button_next: "absolute right-1",
34+
table: "w-full border-collapse space-y-1",
35+
head_row: "flex",
36+
head_cell:
37+
"text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
38+
row: "flex w-full mt-2",
39+
cell: cn(
40+
"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md",
41+
props.mode === "range"
42+
? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md"
43+
: "[&:has([aria-selected])]:rounded-md"
44+
),
45+
day: cn(
46+
buttonVariants({ variant: "ghost" }),
47+
"h-8 w-8 p-0 font-normal aria-selected:opacity-100"
48+
),
49+
day_range_start: "day-range-start",
50+
day_range_end: "day-range-end",
51+
day_selected:
52+
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
53+
day_today: "bg-accent text-accent-foreground",
54+
day_outside:
55+
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
56+
day_disabled: "text-muted-foreground opacity-50",
57+
day_range_middle:
58+
"aria-selected:bg-accent aria-selected:text-accent-foreground",
59+
day_hidden: "invisible",
60+
...classNames,
61+
}}
62+
components={{
63+
IconLeft: ({ ...props }) => <ChevronLeftIcon className="h-4 w-4" />,
64+
IconRight: ({ ...props }) => <ChevronRightIcon className="h-4 w-4" />,
65+
}}
66+
{...props}
67+
/>
68+
)
69+
}
70+
Calendar.displayName = "Calendar"
71+
72+
export { Calendar }
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import * as DialogPrimitive from "@radix-ui/react-dialog"
5+
import { Cross2Icon } from "@radix-ui/react-icons"
6+
7+
import { cn } from "@/lib/utils"
8+
9+
const Dialog = DialogPrimitive.Root
10+
11+
const DialogTrigger = DialogPrimitive.Trigger
12+
13+
const DialogPortal = DialogPrimitive.Portal
14+
15+
const DialogClose = DialogPrimitive.Close
16+
17+
const DialogOverlay = React.forwardRef<
18+
React.ElementRef<typeof DialogPrimitive.Overlay>,
19+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
20+
>(({ className, ...props }, ref) => (
21+
<DialogPrimitive.Overlay
22+
ref={ref}
23+
className={cn(
24+
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
25+
className
26+
)}
27+
{...props}
28+
/>
29+
))
30+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
31+
32+
const DialogContent = React.forwardRef<
33+
React.ElementRef<typeof DialogPrimitive.Content>,
34+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
35+
>(({ className, children, ...props }, ref) => (
36+
<DialogPortal>
37+
<DialogOverlay />
38+
<DialogPrimitive.Content
39+
ref={ref}
40+
className={cn(
41+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
42+
className
43+
)}
44+
{...props}
45+
>
46+
{children}
47+
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
48+
<Cross2Icon className="h-4 w-4" />
49+
<span className="sr-only">Close</span>
50+
</DialogPrimitive.Close>
51+
</DialogPrimitive.Content>
52+
</DialogPortal>
53+
))
54+
DialogContent.displayName = DialogPrimitive.Content.displayName
55+
56+
const DialogHeader = ({
57+
className,
58+
...props
59+
}: React.HTMLAttributes<HTMLDivElement>) => (
60+
<div
61+
className={cn(
62+
"flex flex-col space-y-1.5 text-center sm:text-left",
63+
className
64+
)}
65+
{...props}
66+
/>
67+
)
68+
DialogHeader.displayName = "DialogHeader"
69+
70+
const DialogFooter = ({
71+
className,
72+
...props
73+
}: React.HTMLAttributes<HTMLDivElement>) => (
74+
<div
75+
className={cn(
76+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
77+
className
78+
)}
79+
{...props}
80+
/>
81+
)
82+
DialogFooter.displayName = "DialogFooter"
83+
84+
const DialogTitle = React.forwardRef<
85+
React.ElementRef<typeof DialogPrimitive.Title>,
86+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
87+
>(({ className, ...props }, ref) => (
88+
<DialogPrimitive.Title
89+
ref={ref}
90+
className={cn(
91+
"text-lg font-semibold leading-none tracking-tight",
92+
className
93+
)}
94+
{...props}
95+
/>
96+
))
97+
DialogTitle.displayName = DialogPrimitive.Title.displayName
98+
99+
const DialogDescription = React.forwardRef<
100+
React.ElementRef<typeof DialogPrimitive.Description>,
101+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
102+
>(({ className, ...props }, ref) => (
103+
<DialogPrimitive.Description
104+
ref={ref}
105+
className={cn("text-sm text-muted-foreground", className)}
106+
{...props}
107+
/>
108+
))
109+
DialogDescription.displayName = DialogPrimitive.Description.displayName
110+
111+
export {
112+
Dialog,
113+
DialogPortal,
114+
DialogOverlay,
115+
DialogTrigger,
116+
DialogClose,
117+
DialogContent,
118+
DialogHeader,
119+
DialogFooter,
120+
DialogTitle,
121+
DialogDescription,
122+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as React from "react"
2+
3+
import { cn } from "@/lib/utils"
4+
5+
export interface InputProps
6+
extends React.InputHTMLAttributes<HTMLInputElement> {}
7+
8+
const Input = React.forwardRef<HTMLInputElement, InputProps>(
9+
({ className, type, ...props }, ref) => {
10+
return (
11+
<input
12+
type={type}
13+
className={cn(
14+
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm 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",
15+
className
16+
)}
17+
ref={ref}
18+
{...props}
19+
/>
20+
)
21+
}
22+
)
23+
Input.displayName = "Input"
24+
25+
export { Input }

0 commit comments

Comments
 (0)