1 import React from "react";
2 import * as SheetPrimitive from "@radix-ui/react-dialog";
3 import { cva, type VariantProps } from "class-variance-authority";
4 import { X } from "lucide-react";
5 import { cn } from "@/lib/utils";
6
7 const Sheet = SheetPrimitive.Root;
8 const SheetTrigger = SheetPrimitive.Trigger;
9 const SheetClose = SheetPrimitive.Close;
10 const SheetPortal = SheetPrimitive.Portal;
11
12 const SheetOverlay = React.forwardRef<
13 React.ElementRef<typeof SheetPrimitive.Overlay>,
14 React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
15 >(({ className, ...props }, ref) => (
16 <SheetPrimitive.Overlay
17 className={cn(
18 "fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
19 className
20 )}
21 {...props}
22 ref={ref}
23 />
24 ));
25 SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
26
27 const sheetVariants = cva(
28 "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
29 {
30 variants: {
31 side: {
32 top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
33 bottom:
34 "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
35 left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
36 right:
37 "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
38 },
39 },
40 defaultVariants: {
41 side: "right",
42 },
43 }
44 );
45
46 interface SheetContentProps
47 extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
48 VariantProps<typeof sheetVariants> {}
49
50 const SheetContent = React.forwardRef<
51 React.ElementRef<typeof SheetPrimitive.Content>,
52 SheetContentProps
53 >(({ side = "right", className, children, ...props }, ref) => (
54 <SheetPortal>
55 <SheetOverlay />
56 <SheetPrimitive.Content
57 ref={ref}
58 className={cn(sheetVariants({ side }), className)}
59 {...props}
60 >
61 {children}
62 <SheetPrimitive.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-secondary">
63 <X className="h-4 w-4" />
64 <span className="sr-only">Close</span>
65 </SheetPrimitive.Close>
66 </SheetPrimitive.Content>
67 </SheetPortal>
68 ));
69 SheetContent.displayName = SheetPrimitive.Content.displayName;
70
71 const SheetHeader = ({
72 className,
73 ...props
74 }: React.HTMLAttributes<HTMLDivElement>) => (
75 <div
76 className={cn(
77 "flex flex-col space-y-2 text-center sm:text-left",
78 className
79 )}
80 {...props}
81 />
82 );
83 SheetHeader.displayName = "SheetHeader";
84
85 const SheetFooter = ({
86 className,
87 ...props
88 }: React.HTMLAttributes<HTMLDivElement>) => (
89 <div
90 className={cn(
91 "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
92 className
93 )}
94 {...props}
95 />
96 );
97 SheetFooter.displayName = "SheetFooter";
98
99 const SheetTitle = React.forwardRef<
100 React.ElementRef<typeof SheetPrimitive.Title>,
101 React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
102 >(({ className, ...props }, ref) => (
103 <SheetPrimitive.Title
104 ref={ref}
105 className={cn("text-lg font-semibold text-foreground", className)}
106 {...props}
107 />
108 ));
109 SheetTitle.displayName = SheetPrimitive.Title.displayName;
110
111 const SheetDescription = React.forwardRef<
112 React.ElementRef<typeof SheetPrimitive.Description>,
113 React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
114 >(({ className, ...props }, ref) => (
115 <SheetPrimitive.Description
116 ref={ref}
117 className={cn("text-sm text-muted-foreground", className)}
118 {...props}
119 />
120 ));
121 SheetDescription.displayName = SheetPrimitive.Description.displayName;
122
123 export {
124 Sheet,
125 SheetPortal,
126 SheetOverlay,
127 SheetTrigger,
128 SheetClose,
129 SheetContent,
130 SheetHeader,
131 SheetFooter,
132 SheetTitle,
133 SheetDescription,
134 };