@shadow-js/ui 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +598 -2
  4. package/dist/cli.mjs +2293 -0
  5. package/dist/dev/cli/schema.d.ts +73 -0
  6. package/dist/dev/index.d.ts +6 -0
  7. package/dist/dev/index.js +5 -0
  8. package/dist/dev/locales/ar.d.ts +141 -0
  9. package/dist/dev/locales/ar.js +128 -0
  10. package/dist/dev/locales/ar.js.map +1 -0
  11. package/dist/dev/locales/en.d.ts +141 -0
  12. package/dist/dev/locales/en.js +128 -0
  13. package/dist/dev/locales/en.js.map +1 -0
  14. package/dist/dev/registry/utils/utils.d.ts +29 -0
  15. package/dist/dev/registry/utils/utils.js +27 -0
  16. package/dist/dev/registry/utils/utils.js.map +1 -0
  17. package/dist/dev/theme/theme-logic.d.ts +187 -0
  18. package/dist/dev/theme/theme-logic.js +184 -0
  19. package/dist/dev/theme/theme-logic.js.map +1 -0
  20. package/dist/dev/theme/theme-provider.d.ts +90 -0
  21. package/dist/dev/theme/theme-provider.js +150 -0
  22. package/dist/dev/theme/theme-provider.js.map +1 -0
  23. package/dist/prod/index.js +1 -0
  24. package/dist/prod/locales/ar.js +2 -0
  25. package/dist/prod/locales/ar.js.map +1 -0
  26. package/dist/prod/locales/en.js +2 -0
  27. package/dist/prod/locales/en.js.map +1 -0
  28. package/dist/prod/registry/utils/utils.js +2 -0
  29. package/dist/prod/registry/utils/utils.js.map +1 -0
  30. package/dist/prod/theme/theme-logic.js +2 -0
  31. package/dist/prod/theme/theme-logic.js.map +1 -0
  32. package/dist/prod/theme/theme-provider.js +2 -0
  33. package/dist/prod/theme/theme-provider.js.map +1 -0
  34. package/package.json +102 -4
  35. package/registry/accordion/accordion.tsx +210 -0
  36. package/registry/accordion/item.json +4 -0
  37. package/registry/alert/alert.tsx +200 -0
  38. package/registry/alert/item.json +4 -0
  39. package/registry/alert-dialog/alert-dialog.tsx +530 -0
  40. package/registry/alert-dialog/item.json +4 -0
  41. package/registry/aspect-ratio/aspect-ratio.tsx +71 -0
  42. package/registry/aspect-ratio/item.json +4 -0
  43. package/registry/attachment/attachment.tsx +459 -0
  44. package/registry/attachment/item.json +4 -0
  45. package/registry/avatar/avatar.tsx +385 -0
  46. package/registry/avatar/item.json +4 -0
  47. package/registry/badge/badge.tsx +108 -0
  48. package/registry/badge/item.json +4 -0
  49. package/registry/breadcrumb/breadcrumb.tsx +354 -0
  50. package/registry/breadcrumb/item.json +4 -0
  51. package/registry/bubble/bubble.tsx +260 -0
  52. package/registry/bubble/item.json +4 -0
  53. package/registry/button/button.tsx +125 -0
  54. package/registry/button/item.json +4 -0
  55. package/registry/button-group/button-group.tsx +189 -0
  56. package/registry/button-group/item.json +4 -0
  57. package/registry/calendar/calendar.tsx +348 -0
  58. package/registry/calendar/item.json +4 -0
  59. package/registry/card/card.tsx +311 -0
  60. package/registry/card/item.json +4 -0
  61. package/registry/carousel/carousel.tsx +851 -0
  62. package/registry/carousel/item.json +4 -0
  63. package/registry/chart/chart.tsx +1956 -0
  64. package/registry/chart/item.json +4 -0
  65. package/registry/chart-scale/chart-scale.ts +670 -0
  66. package/registry/chart-scale/item.json +5 -0
  67. package/registry/checkbox/checkbox.tsx +79 -0
  68. package/registry/checkbox/item.json +4 -0
  69. package/registry/code-block/code-block.tsx +470 -0
  70. package/registry/code-block/item.json +4 -0
  71. package/registry/collapsible/collapsible.tsx +117 -0
  72. package/registry/collapsible/item.json +4 -0
  73. package/registry/combobox/combobox.tsx +977 -0
  74. package/registry/combobox/item.json +4 -0
  75. package/registry/command/command.tsx +757 -0
  76. package/registry/command/item.json +4 -0
  77. package/registry/context-menu/context-menu.tsx +697 -0
  78. package/registry/context-menu/item.json +4 -0
  79. package/registry/data-table/data-table.tsx +437 -0
  80. package/registry/data-table/item.json +4 -0
  81. package/registry/date-picker/date-picker.tsx +349 -0
  82. package/registry/date-picker/item.json +4 -0
  83. package/registry/dialog/dialog.tsx +412 -0
  84. package/registry/dialog/item.json +4 -0
  85. package/registry/direction/direction.tsx +88 -0
  86. package/registry/direction/item.json +4 -0
  87. package/registry/drawer/drawer.tsx +787 -0
  88. package/registry/drawer/item.json +4 -0
  89. package/registry/dropdown-menu/dropdown-menu.tsx +692 -0
  90. package/registry/dropdown-menu/item.json +4 -0
  91. package/registry/empty/empty.tsx +240 -0
  92. package/registry/empty/item.json +4 -0
  93. package/registry/field/field.tsx +624 -0
  94. package/registry/field/item.json +4 -0
  95. package/registry/form/form.tsx +1112 -0
  96. package/registry/form/item.json +4 -0
  97. package/registry/hover-card/hover-card.tsx +144 -0
  98. package/registry/hover-card/item.json +4 -0
  99. package/registry/icons/icons.tsx +1691 -0
  100. package/registry/icons/item.json +4 -0
  101. package/registry/input/input.tsx +43 -0
  102. package/registry/input/item.json +4 -0
  103. package/registry/input-group/input-group.tsx +315 -0
  104. package/registry/input-group/item.json +4 -0
  105. package/registry/input-otp/input-otp.tsx +329 -0
  106. package/registry/input-otp/item.json +4 -0
  107. package/registry/item/item.json +4 -0
  108. package/registry/item/item.tsx +439 -0
  109. package/registry/kbd/item.json +4 -0
  110. package/registry/kbd/kbd.tsx +65 -0
  111. package/registry/label/item.json +4 -0
  112. package/registry/label/label.tsx +60 -0
  113. package/registry/marker/item.json +4 -0
  114. package/registry/marker/marker.tsx +175 -0
  115. package/registry/menubar/item.json +4 -0
  116. package/registry/menubar/menubar.tsx +694 -0
  117. package/registry/message/item.json +4 -0
  118. package/registry/message/message.tsx +280 -0
  119. package/registry/message-scroller/item.json +4 -0
  120. package/registry/message-scroller/message-scroller.tsx +262 -0
  121. package/registry/native-select/item.json +4 -0
  122. package/registry/native-select/native-select.tsx +113 -0
  123. package/registry/navigation-menu/item.json +4 -0
  124. package/registry/navigation-menu/navigation-menu.tsx +362 -0
  125. package/registry/pagination/item.json +4 -0
  126. package/registry/pagination/pagination.tsx +460 -0
  127. package/registry/password-input/item.json +5 -0
  128. package/registry/password-input/password-input.tsx +494 -0
  129. package/registry/popover/item.json +4 -0
  130. package/registry/popover/popover.tsx +284 -0
  131. package/registry/progress/item.json +4 -0
  132. package/registry/progress/progress.tsx +190 -0
  133. package/registry/questionnaire/item.json +4 -0
  134. package/registry/questionnaire/questionnaire.tsx +569 -0
  135. package/registry/radio-group/item.json +4 -0
  136. package/registry/radio-group/radio-group.tsx +101 -0
  137. package/registry/resizable/item.json +4 -0
  138. package/registry/resizable/resizable.tsx +455 -0
  139. package/registry/scroll-area/item.json +4 -0
  140. package/registry/scroll-area/scroll-area.tsx +149 -0
  141. package/registry/select/item.json +4 -0
  142. package/registry/select/select.tsx +571 -0
  143. package/registry/separator/item.json +4 -0
  144. package/registry/separator/separator.tsx +52 -0
  145. package/registry/sheet/item.json +4 -0
  146. package/registry/sheet/sheet.tsx +476 -0
  147. package/registry/sidebar/item.json +4 -0
  148. package/registry/sidebar/sidebar.tsx +1870 -0
  149. package/registry/skeleton/item.json +4 -0
  150. package/registry/skeleton/skeleton.tsx +47 -0
  151. package/registry/slider/item.json +4 -0
  152. package/registry/slider/slider.tsx +149 -0
  153. package/registry/spinner/item.json +4 -0
  154. package/registry/spinner/spinner.tsx +51 -0
  155. package/registry/switch/item.json +4 -0
  156. package/registry/switch/switch.tsx +93 -0
  157. package/registry/table/item.json +4 -0
  158. package/registry/table/table.tsx +373 -0
  159. package/registry/tabs/item.json +4 -0
  160. package/registry/tabs/tabs.tsx +209 -0
  161. package/registry/textarea/item.json +4 -0
  162. package/registry/textarea/textarea.tsx +51 -0
  163. package/registry/toast/item.json +4 -0
  164. package/registry/toast/toast.tsx +949 -0
  165. package/registry/toggle/item.json +4 -0
  166. package/registry/toggle/toggle.tsx +110 -0
  167. package/registry/toggle-group/item.json +4 -0
  168. package/registry/toggle-group/toggle-group.tsx +189 -0
  169. package/registry/tooltip/item.json +4 -0
  170. package/registry/tooltip/tooltip.tsx +169 -0
  171. package/registry/trace/item.json +4 -0
  172. package/registry/trace/trace.tsx +356 -0
  173. package/registry/ui-strings/item.json +5 -0
  174. package/registry/ui-strings/ui-strings.tsx +454 -0
  175. package/registry/use-highlighted-code/item.json +5 -0
  176. package/registry/use-highlighted-code/use-highlighted-code.tsx +145 -0
  177. package/registry/use-mobile/item.json +5 -0
  178. package/registry/use-mobile/use-mobile.ts +46 -0
  179. package/registry/utils/item.json +5 -0
  180. package/registry/utils/utils.ts +38 -0
  181. package/registry.json +3274 -0
  182. package/styles/animations.css +321 -0
  183. package/styles/theme-core.css +55 -0
  184. package/styles/theme.css +12 -0
  185. package/styles/themes/gray.css +69 -0
  186. package/styles/themes/neutral.css +69 -0
  187. package/styles/themes/slate.css +69 -0
  188. package/styles/themes/stone.css +69 -0
  189. package/styles/themes/zinc.css +69 -0
  190. package/styles/typeset.css +251 -0
@@ -0,0 +1,476 @@
1
+ import { splitProps } from "@shadow-js/core";
2
+ import {
3
+ type DialogCloseProps,
4
+ type DialogContentProps,
5
+ type DialogDescriptionProps,
6
+ type DialogOverlayProps,
7
+ type DialogPortalProps,
8
+ Dialog as DialogPrimitive,
9
+ type DialogProps,
10
+ type DialogTitleProps,
11
+ type DialogTriggerProps,
12
+ type PolymorphicTarget,
13
+ } from "@shadow-js/primitives";
14
+ import type { ComponentProps, JSX } from "@shadow-js/web";
15
+ import { XIcon } from "@/components/ui/icons";
16
+ import { useUiStrings } from "@/lib/ui-strings";
17
+ import { cn } from "@/lib/utils";
18
+
19
+ /** The positioning, border and slide animation of each side. */
20
+ const SIDES: Record<SheetSide, string> = {
21
+ right:
22
+ "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",
23
+ 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",
24
+ top: "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
25
+ bottom:
26
+ "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
27
+ start:
28
+ "inset-y-0 start-0 h-full w-3/4 border-e data-[state=closed]:ltr:slide-out-to-left data-[state=closed]:rtl:slide-out-to-right data-[state=open]:ltr:slide-in-from-left data-[state=open]:rtl:slide-in-from-right sm:max-w-sm",
29
+ end: "inset-y-0 end-0 h-full w-3/4 border-s data-[state=closed]:ltr:slide-out-to-right data-[state=closed]:rtl:slide-out-to-left data-[state=open]:ltr:slide-in-from-right data-[state=open]:rtl:slide-in-from-left sm:max-w-sm",
30
+ };
31
+
32
+ /**
33
+ * The edge a {@link SheetContent} slides in from. `left` and `right` are the physical edges, as in
34
+ * shadcn/ui. `start` and `end` are the inline-start and inline-end edges, which swap in
35
+ * right-to-left layouts (the border, the position and the slide animation included).
36
+ * @since 1.0.0
37
+ * @see {@link SheetContent}
38
+ */
39
+ export type SheetSide = "top" | "right" | "bottom" | "left" | "start" | "end";
40
+
41
+ /**
42
+ * A modal panel that slides in from an edge of the screen, built on the dialog primitive. Put a
43
+ * {@link SheetTrigger} and a {@link SheetContent} inside it. Control it with `open` and
44
+ * `onOpenChange`, or start it open with `defaultOpen`.
45
+ *
46
+ * Keyboard and ARIA: focus moves into the sheet when it opens and returns to the trigger when it
47
+ * closes. Tab and Shift+Tab cycle inside the sheet. Escape closes it, and so does a press outside
48
+ * the panel (on the overlay). The panel is a `role="dialog"` with `aria-modal="true"`, named by its
49
+ * {@link SheetTitle} and described by its {@link SheetDescription}; while it is open the rest of the
50
+ * page is hidden from assistive technology. A sheet with no title needs an `aria-label` on its
51
+ * content to have a name.
52
+ *
53
+ * shadcn/ui differences: `as` replaces `asChild` on the trigger and the close buttons, and `class`
54
+ * replaces `className`. `side` also takes `"start"` and `"end"` for right-to-left layouts.
55
+ *
56
+ * @param props - The props: `open`, `defaultOpen` and `onOpenChange`, see {@link DialogProps}.
57
+ * @returns The dialog context around the sheet's parts. It renders no element of its own.
58
+ * @example
59
+ * ```tsx
60
+ * import { Button } from "@/components/ui/button";
61
+ * import {
62
+ * Sheet,
63
+ * SheetContent,
64
+ * SheetDescription,
65
+ * SheetHeader,
66
+ * SheetTitle,
67
+ * SheetTrigger,
68
+ * } from "@/components/ui/sheet";
69
+ *
70
+ * export function ProfileSheet() {
71
+ * return (
72
+ * <Sheet>
73
+ * <SheetTrigger as={Button} variant="outline">
74
+ * Edit profile
75
+ * </SheetTrigger>
76
+ * <SheetContent side="right">
77
+ * <SheetHeader>
78
+ * <SheetTitle>Edit profile</SheetTitle>
79
+ * <SheetDescription>Make changes to your profile here.</SheetDescription>
80
+ * </SheetHeader>
81
+ * </SheetContent>
82
+ * </Sheet>
83
+ * );
84
+ * }
85
+ * ```
86
+ * @since 1.0.0
87
+ * @see {@link SheetContent}
88
+ */
89
+ function Sheet(props: DialogProps): JSX.Element {
90
+ return <DialogPrimitive {...props} />;
91
+ }
92
+
93
+ /**
94
+ * The button that opens the sheet. It renders a `button` by default; `as` renders another element,
95
+ * such as a shadcn/ui `Button`.
96
+ *
97
+ * Keyboard and ARIA: Enter and Space activate it. It has `aria-haspopup="dialog"`, `aria-expanded`
98
+ * (`"true"` while the sheet is open) and `aria-controls` pointing at the sheet.
99
+ *
100
+ * shadcn/ui differences: `as` replaces `asChild`, and `class` replaces `className`.
101
+ *
102
+ * @param props - The props: `as` and the attributes of the trigger element.
103
+ * @returns The trigger element.
104
+ * @example
105
+ * ```tsx
106
+ * import { Button } from "@/components/ui/button";
107
+ * import { Sheet, SheetContent, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
108
+ *
109
+ * export function MenuSheet() {
110
+ * return (
111
+ * <Sheet>
112
+ * <SheetTrigger as={Button}>Open</SheetTrigger>
113
+ * <SheetContent>
114
+ * <SheetTitle>Menu</SheetTitle>
115
+ * </SheetContent>
116
+ * </Sheet>
117
+ * );
118
+ * }
119
+ * ```
120
+ * @since 1.0.0
121
+ */
122
+ function SheetTrigger<T extends PolymorphicTarget = "button">(
123
+ props: DialogTriggerProps<T>,
124
+ ): JSX.Element {
125
+ return <DialogPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
126
+ }
127
+
128
+ /**
129
+ * A button that closes the sheet. It renders a `button` by default; `as` renders another element,
130
+ * such as a shadcn/ui `Button`.
131
+ *
132
+ * Keyboard and ARIA: Enter and Space close the sheet. Its name is its text; pass `aria-label` when
133
+ * the text is not descriptive.
134
+ *
135
+ * shadcn/ui differences: `as` replaces `asChild`, and `class` replaces `className`.
136
+ *
137
+ * @param props - The props: `as` and the attributes of the close element.
138
+ * @returns The close element.
139
+ * @example
140
+ * ```tsx
141
+ * import { Button } from "@/components/ui/button";
142
+ * import { Sheet, SheetClose, SheetContent, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
143
+ *
144
+ * export function CancelSheet() {
145
+ * return (
146
+ * <Sheet defaultOpen>
147
+ * <SheetContent>
148
+ * <SheetTitle>Discard changes</SheetTitle>
149
+ * <SheetClose as={Button} variant="outline">
150
+ * Cancel
151
+ * </SheetClose>
152
+ * </SheetContent>
153
+ * </Sheet>
154
+ * );
155
+ * }
156
+ * ```
157
+ * @since 1.0.0
158
+ */
159
+ function SheetClose<T extends PolymorphicTarget = "button">(
160
+ props: DialogCloseProps<T>,
161
+ ): JSX.Element {
162
+ return <DialogPrimitive.Close data-slot="sheet-close" {...props} />;
163
+ }
164
+
165
+ /**
166
+ * Renders the overlay and the content into `document.body` while the sheet is open. {@link SheetContent}
167
+ * already includes one, so you rarely render it yourself. A sheet that is open at render time is
168
+ * server-rendered as well.
169
+ *
170
+ * @param props - The props: `container`, `forceMount`, and `children`.
171
+ * @returns The portal, or nothing while the sheet is closed.
172
+ * @example
173
+ * ```tsx
174
+ * import { Sheet, SheetOverlay, SheetPortal } from "@/components/ui/sheet";
175
+ *
176
+ * export function BackdropOnly() {
177
+ * return (
178
+ * <Sheet defaultOpen>
179
+ * <SheetPortal>
180
+ * <SheetOverlay class="bg-black/70" />
181
+ * </SheetPortal>
182
+ * </Sheet>
183
+ * );
184
+ * }
185
+ * ```
186
+ * @since 1.0.0
187
+ */
188
+ function SheetPortal(props: DialogPortalProps): JSX.Element {
189
+ return <DialogPrimitive.Portal {...props} />;
190
+ }
191
+
192
+ /**
193
+ * The dimmed backdrop behind the sheet. Pressing it closes the sheet.
194
+ *
195
+ * Keyboard and ARIA: `aria-hidden="true"`, and no keys, so assistive technology skips it.
196
+ *
197
+ * shadcn/ui differences: `class` replaces `className`. Its default is `bg-black/50`.
198
+ *
199
+ * @param props - The props: `class`, and the attributes of the overlay element.
200
+ * @returns The overlay element.
201
+ * @example
202
+ * ```tsx
203
+ * import { Sheet, SheetOverlay, SheetPortal } from "@/components/ui/sheet";
204
+ *
205
+ * export function DarkBackdrop() {
206
+ * return (
207
+ * <Sheet defaultOpen>
208
+ * <SheetPortal>
209
+ * <SheetOverlay class="bg-black/70" />
210
+ * </SheetPortal>
211
+ * </Sheet>
212
+ * );
213
+ * }
214
+ * ```
215
+ * @since 1.0.0
216
+ * @see {@link SheetPortal}
217
+ */
218
+ function SheetOverlay(props: DialogOverlayProps): JSX.Element {
219
+ const [local, rest] = splitProps(props, ["class"]);
220
+ return (
221
+ <DialogPrimitive.Overlay
222
+ data-slot="sheet-overlay"
223
+ class={cn(
224
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
225
+ local.class,
226
+ )}
227
+ {...rest}
228
+ />
229
+ );
230
+ }
231
+
232
+ /**
233
+ * Own props of {@link SheetContent}.
234
+ * @since 1.0.0
235
+ * @see {@link SheetContent}
236
+ */
237
+ export interface SheetContentExtraProps {
238
+ /**
239
+ * The edge the sheet slides in from.
240
+ * @default "right"
241
+ */
242
+ readonly side?: SheetSide | undefined;
243
+ /**
244
+ * Show the close button in the corner.
245
+ * @default true
246
+ */
247
+ readonly showCloseButton?: boolean | undefined;
248
+ }
249
+
250
+ /**
251
+ * The sheet panel: the portal, the overlay, and the content anchored to `side`. It holds the
252
+ * header, the body and the footer. A close button sits in the top corner on the end edge unless
253
+ * `showCloseButton` is `false`.
254
+ *
255
+ * Keyboard and ARIA: see {@link Sheet}. The panel is a `role="dialog"`. The close button is named
256
+ * "Close" (a visually hidden label) and closes the sheet on Enter or Space.
257
+ *
258
+ * shadcn/ui differences: `side` also takes `"start"` and `"end"`, and `showCloseButton` (default
259
+ * `true`) removes the built-in close button when `false`.
260
+ *
261
+ * @param props - The props: `side`, `showCloseButton`, and the attributes of the dialog content.
262
+ * @returns The portal, with the overlay and the content inside.
263
+ * @example
264
+ * ```tsx
265
+ * import { Sheet, SheetContent, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
266
+ *
267
+ * export function MenuSheet() {
268
+ * return (
269
+ * <Sheet>
270
+ * <SheetTrigger>Menu</SheetTrigger>
271
+ * <SheetContent side="left" showCloseButton={false}>
272
+ * <SheetTitle>Menu</SheetTitle>
273
+ * </SheetContent>
274
+ * </Sheet>
275
+ * );
276
+ * }
277
+ * ```
278
+ * @since 1.0.0
279
+ */
280
+ function SheetContent(props: DialogContentProps & SheetContentExtraProps): JSX.Element {
281
+ const [local, rest] = splitProps(props, ["class", "children", "side", "showCloseButton"]);
282
+ const t = useUiStrings();
283
+ return (
284
+ <SheetPortal>
285
+ <SheetOverlay />
286
+ <DialogPrimitive.Content
287
+ data-slot="sheet-content"
288
+ class={cn(
289
+ "fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out outline-none motion-reduce:transition-none data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:animate-in data-[state=open]:duration-500",
290
+ SIDES[local.side ?? "right"],
291
+ local.class,
292
+ )}
293
+ {...rest}
294
+ >
295
+ {local.children}
296
+ {local.showCloseButton !== false && (
297
+ <DialogPrimitive.Close
298
+ data-slot="sheet-close"
299
+ class="absolute end-4 top-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 outline-none focus:outline-solid focus:outline-2 focus:outline-offset-2 focus:outline-transparent disabled:pointer-events-none data-[state=open]:bg-secondary motion-reduce:transition-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
300
+ >
301
+ <XIcon />
302
+ <span class="sr-only">{t("sheet.close", "Close")}</span>
303
+ </DialogPrimitive.Close>
304
+ )}
305
+ </DialogPrimitive.Content>
306
+ </SheetPortal>
307
+ );
308
+ }
309
+
310
+ /**
311
+ * The layout of the title and the description at the top of the sheet.
312
+ *
313
+ * Keyboard and ARIA: no keys and no role of its own.
314
+ *
315
+ * shadcn/ui differences: `class` replaces `className`.
316
+ *
317
+ * @param props - The props: the attributes of the `div`, and `class`.
318
+ * @returns The header `div`.
319
+ * @example
320
+ * ```tsx
321
+ * import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
322
+ *
323
+ * export function Header() {
324
+ * return (
325
+ * <Sheet>
326
+ * <SheetTrigger>Open</SheetTrigger>
327
+ * <SheetContent>
328
+ * <SheetHeader>
329
+ * <SheetTitle>Edit profile</SheetTitle>
330
+ * <SheetDescription>Make changes to your profile here.</SheetDescription>
331
+ * </SheetHeader>
332
+ * </SheetContent>
333
+ * </Sheet>
334
+ * );
335
+ * }
336
+ * ```
337
+ * @since 1.0.0
338
+ */
339
+ function SheetHeader(props: ComponentProps<"div">): JSX.Element {
340
+ const [local, rest] = splitProps(props, ["class"]);
341
+ return (
342
+ <div data-slot="sheet-header" class={cn("flex flex-col gap-1.5 p-4", local.class)} {...rest} />
343
+ );
344
+ }
345
+
346
+ /**
347
+ * The layout of the action buttons at the bottom of the sheet. It is pushed to the bottom of the
348
+ * panel.
349
+ *
350
+ * Keyboard and ARIA: no keys and no role of its own.
351
+ *
352
+ * shadcn/ui differences: `class` replaces `className`.
353
+ *
354
+ * @param props - The props: the attributes of the `div`, and `class`.
355
+ * @returns The footer `div`.
356
+ * @example
357
+ * ```tsx
358
+ * import { Button } from "@/components/ui/button";
359
+ * import { Sheet, SheetClose, SheetContent, SheetFooter, SheetTrigger } from "@/components/ui/sheet";
360
+ *
361
+ * export function Actions() {
362
+ * return (
363
+ * <Sheet>
364
+ * <SheetTrigger>Open</SheetTrigger>
365
+ * <SheetContent>
366
+ * <SheetFooter>
367
+ * <SheetClose as={Button}>Save</SheetClose>
368
+ * </SheetFooter>
369
+ * </SheetContent>
370
+ * </Sheet>
371
+ * );
372
+ * }
373
+ * ```
374
+ * @since 1.0.0
375
+ */
376
+ function SheetFooter(props: ComponentProps<"div">): JSX.Element {
377
+ const [local, rest] = splitProps(props, ["class"]);
378
+ return (
379
+ <div
380
+ data-slot="sheet-footer"
381
+ class={cn("mt-auto flex flex-col gap-2 p-4", local.class)}
382
+ {...rest}
383
+ />
384
+ );
385
+ }
386
+
387
+ /**
388
+ * The title of the sheet. It is the sheet's accessible name, so give every sheet a title.
389
+ *
390
+ * Keyboard and ARIA: no keys. The sheet's `aria-labelledby` points at this title.
391
+ *
392
+ * shadcn/ui differences: `class` replaces `className`.
393
+ *
394
+ * @param props - The props: the attributes of the title element, and `class`.
395
+ * @returns The title element.
396
+ * @example
397
+ * ```tsx
398
+ * import { Sheet, SheetContent, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
399
+ *
400
+ * export function TitledSheet() {
401
+ * return (
402
+ * <Sheet>
403
+ * <SheetTrigger>Open</SheetTrigger>
404
+ * <SheetContent>
405
+ * <SheetTitle>Edit profile</SheetTitle>
406
+ * </SheetContent>
407
+ * </Sheet>
408
+ * );
409
+ * }
410
+ * ```
411
+ * @since 1.0.0
412
+ * @see {@link SheetDescription}
413
+ */
414
+ function SheetTitle(props: DialogTitleProps): JSX.Element {
415
+ const [local, rest] = splitProps(props, ["class"]);
416
+ return (
417
+ <DialogPrimitive.Title
418
+ data-slot="sheet-title"
419
+ class={cn("font-semibold text-foreground", local.class)}
420
+ {...rest}
421
+ />
422
+ );
423
+ }
424
+
425
+ /**
426
+ * The description of the sheet, read after its title.
427
+ *
428
+ * Keyboard and ARIA: no keys. The sheet's `aria-describedby` points at this description while it is
429
+ * rendered.
430
+ *
431
+ * shadcn/ui differences: `class` replaces `className`.
432
+ *
433
+ * @param props - The props: the attributes of the description element, and `class`.
434
+ * @returns The description element.
435
+ * @example
436
+ * ```tsx
437
+ * import { Sheet, SheetContent, SheetDescription, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
438
+ *
439
+ * export function DescribedSheet() {
440
+ * return (
441
+ * <Sheet>
442
+ * <SheetTrigger>Open</SheetTrigger>
443
+ * <SheetContent>
444
+ * <SheetTitle>Edit profile</SheetTitle>
445
+ * <SheetDescription>Make changes here.</SheetDescription>
446
+ * </SheetContent>
447
+ * </Sheet>
448
+ * );
449
+ * }
450
+ * ```
451
+ * @since 1.0.0
452
+ * @see {@link SheetTitle}
453
+ */
454
+ function SheetDescription(props: DialogDescriptionProps): JSX.Element {
455
+ const [local, rest] = splitProps(props, ["class"]);
456
+ return (
457
+ <DialogPrimitive.Description
458
+ data-slot="sheet-description"
459
+ class={cn("text-sm text-muted-foreground", local.class)}
460
+ {...rest}
461
+ />
462
+ );
463
+ }
464
+
465
+ export {
466
+ Sheet,
467
+ SheetClose,
468
+ SheetContent,
469
+ SheetDescription,
470
+ SheetFooter,
471
+ SheetHeader,
472
+ SheetOverlay,
473
+ SheetPortal,
474
+ SheetTitle,
475
+ SheetTrigger,
476
+ };
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Sidebar",
3
+ "description": "A composable, collapsible sidebar that becomes a sheet on mobile, with menus, groups, tooltips and a Ctrl/Cmd+B shortcut."
4
+ }