← full-stack-fastapi-template  /  frontend/src/components/ui/sheet.tsx

1
"use client"
2
3
import * as React from "react"
4
import * as SheetPrimitive from "@radix-ui/react-dialog"
5
import { XIcon } from "lucide-react"
6
7
import { cn } from "@/lib/utils"
8
9
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
10
  return <SheetPrimitive.Root data-slot="sheet" {...props} />
11
}
12
13
function SheetTrigger({
14
  ...props
15
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
16
  return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
17
}
18
19
function SheetClose({
20
  ...props
21
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
22
  return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
23
}
24
25
function SheetPortal({
26
  ...props
27
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
28
  return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
29
}
30
31
function SheetOverlay({
32
  className,
33
  ...props
34
}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
35
  return (
36
    <SheetPrimitive.Overlay
37
      data-slot="sheet-overlay"
38
      className={cn(
39
        "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
40
        className
41
      )}
42
      {...props}
43
    />
44
  )
45
}
46
47
function SheetContent({
48
  className,
49
  children,
50
  side = "right",
51
  ...props
52
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
53
  side?: "top" | "right" | "bottom" | "left"
54
}) {
55
  return (
56
    <SheetPortal>
57
      <SheetOverlay />
58
      <SheetPrimitive.Content
59
        data-slot="sheet-content"
60
        className={cn(
61
          "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
62
          side === "right" &&
63
            "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
64
          side === "left" &&
65
            "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
66
          side === "top" &&
67
            "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
68
          side === "bottom" &&
69
            "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
70
          className
71
        )}
72
        {...props}
73
      >
74
        {children}
75
        <SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
76
          <XIcon className="size-4" />
77
          <span className="sr-only">Close</span>
78
        </SheetPrimitive.Close>
79
      </SheetPrimitive.Content>
80
    </SheetPortal>
81
  )
82
}
83
84
function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
85
  return (
86
    <div
87
      data-slot="sheet-header"
88
      className={cn("flex flex-col gap-1.5 p-4", className)}
89
      {...props}
90
    />
91
  )
92
}
93
94
function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
95
  return (
96
    <div
97
      data-slot="sheet-footer"
98
      className={cn("mt-auto flex flex-col gap-2 p-4", className)}
99
      {...props}
100
    />
101
  )
102
}
103
104
function SheetTitle({
105
  className,
106
  ...props
107
}: React.ComponentProps<typeof SheetPrimitive.Title>) {
108
  return (
109
    <SheetPrimitive.Title
110
      data-slot="sheet-title"
111
      className={cn("text-foreground font-semibold", className)}
112
      {...props}
113
    />
114
  )
115
}
116
117
function SheetDescription({
118
  className,
119
  ...props
120
}: React.ComponentProps<typeof SheetPrimitive.Description>) {
121
  return (
122
    <SheetPrimitive.Description
123
      data-slot="sheet-description"
124
      className={cn("text-muted-foreground text-sm", className)}
125
      {...props}
126
    />
127
  )
128
}
129
130
export {
131
  Sheet,
132
  SheetTrigger,
133
  SheetClose,
134
  SheetContent,
135
  SheetHeader,
136
  SheetFooter,
137
  SheetTitle,
138
  SheetDescription,
139
}
140