@inspirare/design-system 0.0.22 → 0.0.24
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.
- package/README.md +82 -61
- package/dist/book-logo-filled.svg +55 -0
- package/dist/components/ui/accessibility-improvements.js +26 -23
- package/dist/components/ui/accordion.js +34 -24
- package/dist/components/ui/alert-dialog.js +91 -57
- package/dist/components/ui/alert.js +38 -26
- package/dist/components/ui/aspect-ratio.js +11 -3
- package/dist/components/ui/avatar.js +30 -8
- package/dist/components/ui/badge.js +20 -14
- package/dist/components/ui/breadcrumb.js +69 -56
- package/dist/components/ui/button-group.js +17 -13
- package/dist/components/ui/button.js +19 -15
- package/dist/components/ui/calendar.js +63 -59
- package/dist/components/ui/card.js +11 -9
- package/dist/components/ui/carousel.js +70 -75
- package/dist/components/ui/chart.js +75 -72
- package/dist/components/ui/checkbox.js +4 -5
- package/dist/components/ui/collapsible.js +12 -14
- package/dist/components/ui/color-picker.js +60 -80
- package/dist/components/ui/combobox.js +153 -33
- package/dist/components/ui/command.js +50 -48
- package/dist/components/ui/context-menu.js +129 -68
- package/dist/components/ui/dialog.js +65 -60
- package/dist/components/ui/drawer.js +81 -40
- package/dist/components/ui/dropdown-menu.js +100 -87
- package/dist/components/ui/empty.js +7 -6
- package/dist/components/ui/field.js +44 -47
- package/dist/components/ui/form.js +22 -23
- package/dist/components/ui/hover-card.js +14 -11
- package/dist/components/ui/input-group.js +16 -13
- package/dist/components/ui/input-otp.js +37 -32
- package/dist/components/ui/input.js +9 -7
- package/dist/components/ui/item.js +42 -36
- package/dist/components/ui/kbd.js +2 -1
- package/dist/components/ui/label.js +6 -7
- package/dist/components/ui/menubar.js +124 -93
- package/dist/components/ui/navigation-menu.js +79 -54
- package/dist/components/ui/pagination.js +78 -58
- package/dist/components/ui/popover.js +35 -16
- package/dist/components/ui/progress.js +37 -13
- package/dist/components/ui/radio-group.js +14 -14
- package/dist/components/ui/resizable.js +24 -15
- package/dist/components/ui/scroll-area.js +29 -11
- package/dist/components/ui/select.js +98 -56
- package/dist/components/ui/separator.js +5 -7
- package/dist/components/ui/sheet.js +47 -42
- package/dist/components/ui/sidebar.js +279 -248
- package/dist/components/ui/skeleton.js +4 -40
- package/dist/components/ui/slider.js +27 -29
- package/dist/components/ui/sonner.js +27 -10
- package/dist/components/ui/spinner.js +2 -0
- package/dist/components/ui/switch.js +3 -4
- package/dist/components/ui/table.js +6 -6
- package/dist/components/ui/tabs.js +45 -22
- package/dist/components/ui/textarea.js +3 -2
- package/dist/components/ui/theme-toggle.js +38 -41
- package/dist/components/ui/toggle-group.js +30 -21
- package/dist/components/ui/toggle.js +8 -9
- package/dist/components/ui/tooltip.js +28 -23
- package/dist/index.css +1 -1
- package/dist/index.d.ts +446 -468
- package/dist/index.js +58 -58
- package/package.json +42 -41
- package/src/App.tsx +28 -34
- package/src/components/branding/assets/book-logo-filled.svg +55 -0
- package/src/components/branding/logo/logo.tsx +56 -0
- package/src/components/ui/accessibility-improvements.stories.tsx +18 -0
- package/src/components/ui/accessibility-improvements.test.tsx +13 -0
- package/src/components/ui/accessibility-improvements.tsx +16 -6
- package/src/components/ui/accordion.stories.tsx +19 -0
- package/src/components/ui/accordion.test.tsx +14 -0
- package/src/components/ui/accordion.tsx +28 -20
- package/src/components/ui/alert-dialog.stories.tsx +19 -0
- package/src/components/ui/alert-dialog.test.tsx +14 -0
- package/src/components/ui/alert-dialog.tsx +159 -123
- package/src/components/ui/alert.stories.tsx +19 -0
- package/src/components/ui/alert.test.tsx +14 -0
- package/src/components/ui/alert.tsx +60 -41
- package/src/components/ui/aspect-ratio.stories.tsx +19 -0
- package/src/components/ui/aspect-ratio.test.tsx +14 -0
- package/src/components/ui/aspect-ratio.tsx +19 -2
- package/src/components/ui/attachment.stories.tsx +19 -0
- package/src/components/ui/attachment.test.tsx +14 -0
- package/src/components/ui/attachment.tsx +209 -0
- package/src/components/ui/avatar.stories.tsx +19 -0
- package/src/components/ui/avatar.test.tsx +14 -0
- package/src/components/ui/avatar.tsx +73 -17
- package/src/components/ui/badge.stories.tsx +19 -0
- package/src/components/ui/badge.test.tsx +14 -0
- package/src/components/ui/badge.tsx +33 -25
- package/src/components/ui/breadcrumb.stories.tsx +19 -0
- package/src/components/ui/breadcrumb.test.tsx +14 -0
- package/src/components/ui/breadcrumb.tsx +98 -86
- package/src/components/ui/bubble.stories.tsx +19 -0
- package/src/components/ui/bubble.test.tsx +14 -0
- package/src/components/ui/bubble.tsx +130 -0
- package/src/components/ui/button-group.stories.tsx +19 -0
- package/src/components/ui/button-group.test.tsx +14 -0
- package/src/components/ui/button-group.tsx +26 -20
- package/src/components/ui/button.stories.tsx +19 -0
- package/src/components/ui/button.test.tsx +14 -0
- package/src/components/ui/button.tsx +30 -31
- package/src/components/ui/calendar.stories.tsx +19 -0
- package/src/components/ui/calendar.test.tsx +14 -0
- package/src/components/ui/calendar.tsx +28 -26
- package/src/components/ui/card.stories.tsx +19 -0
- package/src/components/ui/card.test.tsx +14 -0
- package/src/components/ui/card.tsx +30 -17
- package/src/components/ui/carousel.stories.tsx +19 -0
- package/src/components/ui/carousel.test.tsx +14 -0
- package/src/components/ui/carousel.tsx +115 -135
- package/src/components/ui/chart.stories.tsx +18 -0
- package/src/components/ui/chart.test.tsx +13 -0
- package/src/components/ui/chart.tsx +220 -216
- package/src/components/ui/checkbox.stories.tsx +19 -0
- package/src/components/ui/checkbox.test.tsx +14 -0
- package/src/components/ui/checkbox.tsx +7 -10
- package/src/components/ui/collapsible.stories.tsx +19 -0
- package/src/components/ui/collapsible.test.tsx +14 -0
- package/src/components/ui/collapsible.tsx +11 -26
- package/src/components/ui/color-picker.stories.tsx +19 -0
- package/src/components/ui/color-picker.test.tsx +14 -0
- package/src/components/ui/color-picker.tsx +36 -26
- package/src/components/ui/combobox.stories.tsx +19 -0
- package/src/components/ui/combobox.test.tsx +14 -0
- package/src/components/ui/combobox.tsx +281 -96
- package/src/components/ui/command.stories.tsx +19 -0
- package/src/components/ui/command.test.tsx +14 -0
- package/src/components/ui/command.tsx +59 -47
- package/src/components/ui/context-menu.stories.tsx +19 -0
- package/src/components/ui/context-menu.test.tsx +14 -0
- package/src/components/ui/context-menu.tsx +231 -160
- package/src/components/ui/dialog.stories.tsx +19 -0
- package/src/components/ui/dialog.test.tsx +14 -0
- package/src/components/ui/dialog.tsx +81 -72
- package/src/components/ui/direction.stories.tsx +19 -0
- package/src/components/ui/direction.test.tsx +14 -0
- package/src/components/ui/direction.tsx +6 -0
- package/src/components/ui/drawer.stories.tsx +19 -0
- package/src/components/ui/drawer.test.tsx +14 -0
- package/src/components/ui/drawer.tsx +143 -64
- package/src/components/ui/dropdown-menu.stories.tsx +19 -0
- package/src/components/ui/dropdown-menu.test.tsx +14 -0
- package/src/components/ui/dropdown-menu.tsx +199 -153
- package/src/components/ui/empty.stories.tsx +18 -0
- package/src/components/ui/empty.test.tsx +13 -0
- package/src/components/ui/empty.tsx +11 -9
- package/src/components/ui/field.stories.tsx +18 -0
- package/src/components/ui/field.test.tsx +13 -0
- package/src/components/ui/field.tsx +26 -32
- package/src/components/ui/form.stories.tsx +22 -0
- package/src/components/ui/form.test.tsx +15 -0
- package/src/components/ui/form.tsx +1 -2
- package/src/components/ui/hover-card.stories.tsx +19 -0
- package/src/components/ui/hover-card.test.tsx +14 -0
- package/src/components/ui/hover-card.tsx +34 -32
- package/src/components/ui/input-group.stories.tsx +18 -0
- package/src/components/ui/input-group.test.tsx +13 -0
- package/src/components/ui/input-group.tsx +21 -28
- package/src/components/ui/input-otp.stories.tsx +19 -0
- package/src/components/ui/input-otp.test.tsx +14 -0
- package/src/components/ui/input-otp.tsx +58 -42
- package/src/components/ui/input.stories.tsx +19 -0
- package/src/components/ui/input.test.tsx +14 -0
- package/src/components/ui/input.tsx +9 -8
- package/src/components/ui/item.stories.tsx +18 -0
- package/src/components/ui/item.test.tsx +13 -0
- package/src/components/ui/item.tsx +38 -28
- package/src/components/ui/kbd.stories.tsx +18 -0
- package/src/components/ui/kbd.test.tsx +13 -0
- package/src/components/ui/kbd.tsx +3 -3
- package/src/components/ui/label.stories.tsx +18 -0
- package/src/components/ui/label.test.tsx +13 -0
- package/src/components/ui/label.tsx +7 -11
- package/src/components/ui/marker.stories.tsx +19 -0
- package/src/components/ui/marker.test.tsx +14 -0
- package/src/components/ui/marker.tsx +73 -0
- package/src/components/ui/menubar.stories.tsx +19 -0
- package/src/components/ui/menubar.test.tsx +14 -0
- package/src/components/ui/menubar.tsx +226 -202
- package/src/components/ui/message-scroller.stories.tsx +19 -0
- package/src/components/ui/message-scroller.test.tsx +14 -0
- package/src/components/ui/message-scroller.tsx +131 -0
- package/src/components/ui/message.stories.tsx +19 -0
- package/src/components/ui/message.test.tsx +14 -0
- package/src/components/ui/message.tsx +94 -0
- package/src/components/ui/native-select.stories.tsx +18 -0
- package/src/components/ui/native-select.test.tsx +13 -0
- package/src/components/ui/native-select.tsx +63 -0
- package/src/components/ui/navigation-menu.stories.tsx +19 -0
- package/src/components/ui/navigation-menu.test.tsx +14 -0
- package/src/components/ui/navigation-menu.tsx +145 -103
- package/src/components/ui/pagination.stories.tsx +19 -0
- package/src/components/ui/pagination.test.tsx +14 -0
- package/src/components/ui/pagination.tsx +114 -83
- package/src/components/ui/popover.stories.tsx +19 -0
- package/src/components/ui/popover.test.tsx +14 -0
- package/src/components/ui/popover.tsx +68 -33
- package/src/components/ui/progress.stories.tsx +19 -0
- package/src/components/ui/progress.test.tsx +14 -0
- package/src/components/ui/progress.tsx +67 -15
- package/src/components/ui/questionnaire.stories.tsx +19 -0
- package/src/components/ui/questionnaire.test.tsx +14 -0
- package/src/components/ui/questionnaire.tsx +324 -0
- package/src/components/ui/radio-group.stories.tsx +19 -0
- package/src/components/ui/radio-group.test.tsx +14 -0
- package/src/components/ui/radio-group.tsx +15 -20
- package/src/components/ui/resizable.stories.tsx +19 -0
- package/src/components/ui/resizable.test.tsx +14 -0
- package/src/components/ui/resizable.tsx +37 -30
- package/src/components/ui/scroll-area.stories.tsx +19 -0
- package/src/components/ui/scroll-area.test.tsx +14 -0
- package/src/components/ui/scroll-area.tsx +41 -19
- package/src/components/ui/select.stories.tsx +19 -0
- package/src/components/ui/select.test.tsx +14 -0
- package/src/components/ui/select.tsx +145 -78
- package/src/components/ui/separator.stories.tsx +19 -0
- package/src/components/ui/separator.test.tsx +14 -0
- package/src/components/ui/separator.tsx +8 -11
- package/src/components/ui/sheet.stories.tsx +19 -0
- package/src/components/ui/sheet.test.tsx +14 -0
- package/src/components/ui/sheet.tsx +56 -71
- package/src/components/ui/sidebar.stories.tsx +18 -0
- package/src/components/ui/sidebar.test.tsx +13 -0
- package/src/components/ui/sidebar.tsx +469 -513
- package/src/components/ui/skeleton.stories.tsx +19 -0
- package/src/components/ui/skeleton.test.tsx +14 -0
- package/src/components/ui/skeleton.tsx +8 -114
- package/src/components/ui/slider.stories.tsx +19 -0
- package/src/components/ui/slider.test.tsx +14 -0
- package/src/components/ui/slider.tsx +31 -40
- package/src/components/ui/sonner.stories.tsx +19 -0
- package/src/components/ui/sonner.test.tsx +14 -0
- package/src/components/ui/sonner.tsx +39 -7
- package/src/components/ui/spinner.stories.tsx +18 -0
- package/src/components/ui/spinner.test.tsx +13 -0
- package/src/components/ui/spinner.tsx +3 -7
- package/src/components/ui/switch.stories.tsx +19 -0
- package/src/components/ui/switch.test.tsx +14 -0
- package/src/components/ui/switch.tsx +4 -7
- package/src/components/ui/table.stories.tsx +19 -0
- package/src/components/ui/table.test.tsx +14 -0
- package/src/components/ui/table.tsx +17 -17
- package/src/components/ui/tabs.stories.tsx +19 -0
- package/src/components/ui/tabs.test.tsx +14 -0
- package/src/components/ui/tabs.tsx +71 -31
- package/src/components/ui/textarea.stories.tsx +19 -0
- package/src/components/ui/textarea.test.tsx +14 -0
- package/src/components/ui/textarea.tsx +7 -5
- package/src/components/ui/theme-toggle.stories.tsx +18 -0
- package/src/components/ui/theme-toggle.test.tsx +13 -0
- package/src/components/ui/theme-toggle.tsx +35 -37
- package/src/components/ui/toggle-group.stories.tsx +19 -0
- package/src/components/ui/toggle-group.test.tsx +14 -0
- package/src/components/ui/toggle-group.tsx +41 -25
- package/src/components/ui/toggle.stories.tsx +19 -0
- package/src/components/ui/toggle.test.tsx +14 -0
- package/src/components/ui/toggle.tsx +17 -19
- package/src/components/ui/tooltip.stories.tsx +19 -0
- package/src/components/ui/tooltip.test.tsx +14 -0
- package/src/components/ui/tooltip.tsx +53 -44
- package/src/demo/AIDemo.tsx +50 -0
- package/src/demo/ButtonsDemo.tsx +41 -18
- package/src/demo/CalendarDemo.tsx +1 -1
- package/src/demo/FeedbackDemo.tsx +4 -6
- package/src/demo/FormsDemo.tsx +34 -11
- package/src/demo/NavigationDemo.tsx +38 -13
- package/src/demo/OverlaysDemo.tsx +22 -36
- package/src/demo/update-demos.js +82 -0
- package/src/index.css +66 -46
- package/src/lib/utils.ts +3 -3
- package/src/stories/Button.stories.ts +54 -0
- package/src/stories/Button.tsx +36 -0
- package/src/stories/Configure.mdx +388 -0
- package/src/stories/Header.stories.ts +34 -0
- package/src/stories/Header.tsx +55 -0
- package/src/stories/Page.stories.ts +33 -0
- package/src/stories/Page.tsx +73 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/stories/button.css +30 -0
- package/src/stories/header.css +32 -0
- package/src/stories/page.css +68 -0
|
@@ -1,80 +1,64 @@
|
|
|
1
|
-
"use client"
|
|
1
|
+
"use client"
|
|
2
2
|
|
|
3
|
-
import * as
|
|
4
|
-
import {
|
|
5
|
-
import * as React from "react";
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
|
|
6
5
|
|
|
7
|
-
import { cn } from "@/lib/utils"
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
import { Button } from "@/components/ui/button"
|
|
8
|
+
import { XIcon } from "lucide-react"
|
|
8
9
|
|
|
9
|
-
function Dialog({
|
|
10
|
-
...props
|
|
11
|
-
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
12
|
-
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
10
|
+
function Dialog({ ...props }: DialogPrimitive.Root.Props) {
|
|
11
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
return
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
className={cn("cursor-pointer", className)}
|
|
23
|
-
{...props}
|
|
24
|
-
/>
|
|
25
|
-
);
|
|
26
|
-
}
|
|
14
|
+
const DialogTrigger = React.forwardRef<
|
|
15
|
+
React.ElementRef<"button">,
|
|
16
|
+
DialogPrimitive.Trigger.Props
|
|
17
|
+
>(({ ...props }, ref) => {
|
|
18
|
+
return <DialogPrimitive.Trigger ref={ref} data-slot="dialog-trigger" {...props} />
|
|
19
|
+
})
|
|
20
|
+
DialogTrigger.displayName = "DialogTrigger"
|
|
27
21
|
|
|
28
|
-
function DialogPortal({
|
|
29
|
-
...props
|
|
30
|
-
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
31
|
-
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
22
|
+
function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
|
|
23
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
|
32
24
|
}
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
className={cn("cursor-pointer", className)}
|
|
42
|
-
{...props}
|
|
43
|
-
/>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
26
|
+
const DialogClose = React.forwardRef<
|
|
27
|
+
React.ElementRef<"button">,
|
|
28
|
+
DialogPrimitive.Close.Props
|
|
29
|
+
>(({ ...props }, ref) => {
|
|
30
|
+
return <DialogPrimitive.Close ref={ref} data-slot="dialog-close" {...props} />
|
|
31
|
+
})
|
|
32
|
+
DialogClose.displayName = "DialogClose"
|
|
46
33
|
|
|
47
34
|
function DialogOverlay({
|
|
48
35
|
className,
|
|
49
36
|
...props
|
|
50
|
-
}:
|
|
37
|
+
}: DialogPrimitive.Backdrop.Props) {
|
|
51
38
|
return (
|
|
52
|
-
<DialogPrimitive.
|
|
39
|
+
<DialogPrimitive.Backdrop
|
|
53
40
|
data-slot="dialog-overlay"
|
|
54
41
|
className={cn(
|
|
55
|
-
"data-
|
|
42
|
+
"fixed inset-0 isolate z-50 bg-black/80 backdrop-blur-sm duration-200 data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
|
56
43
|
className
|
|
57
44
|
)}
|
|
58
45
|
{...props}
|
|
59
46
|
/>
|
|
60
|
-
)
|
|
47
|
+
)
|
|
61
48
|
}
|
|
62
49
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
...props
|
|
68
|
-
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
69
|
-
showCloseButton?: boolean;
|
|
70
|
-
}) {
|
|
50
|
+
const DialogContent = React.forwardRef<
|
|
51
|
+
React.ElementRef<"div">,
|
|
52
|
+
DialogPrimitive.Popup.Props & { showCloseButton?: boolean }
|
|
53
|
+
>(({ className, children, showCloseButton = true, ...props }, ref) => {
|
|
71
54
|
return (
|
|
72
|
-
<DialogPortal
|
|
55
|
+
<DialogPortal>
|
|
73
56
|
<DialogOverlay />
|
|
74
|
-
<DialogPrimitive.
|
|
57
|
+
<DialogPrimitive.Popup
|
|
58
|
+
ref={ref}
|
|
75
59
|
data-slot="dialog-content"
|
|
76
60
|
className={cn(
|
|
77
|
-
"
|
|
61
|
+
"fixed top-1/2 left-1/2 z-50 grid w-[90vw] max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 rounded-2xl bg-popover/90 backdrop-blur-xl p-6 text-sm text-popover-foreground shadow-2xl ring-1 ring-border duration-200 outline-none data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
78
62
|
className
|
|
79
63
|
)}
|
|
80
64
|
{...props}
|
|
@@ -83,64 +67,89 @@ function DialogContent({
|
|
|
83
67
|
{showCloseButton && (
|
|
84
68
|
<DialogPrimitive.Close
|
|
85
69
|
data-slot="dialog-close"
|
|
86
|
-
|
|
70
|
+
render={
|
|
71
|
+
<Button
|
|
72
|
+
variant="ghost"
|
|
73
|
+
className="absolute top-4 right-4 rounded-full"
|
|
74
|
+
size="icon-sm"
|
|
75
|
+
/>
|
|
76
|
+
}
|
|
87
77
|
>
|
|
88
78
|
<XIcon />
|
|
89
79
|
<span className="sr-only">Close</span>
|
|
90
80
|
</DialogPrimitive.Close>
|
|
91
81
|
)}
|
|
92
|
-
</DialogPrimitive.
|
|
82
|
+
</DialogPrimitive.Popup>
|
|
93
83
|
</DialogPortal>
|
|
94
|
-
)
|
|
95
|
-
}
|
|
84
|
+
)
|
|
85
|
+
})
|
|
86
|
+
DialogContent.displayName = "DialogContent"
|
|
96
87
|
|
|
97
88
|
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
98
89
|
return (
|
|
99
90
|
<div
|
|
100
91
|
data-slot="dialog-header"
|
|
101
|
-
className={cn("flex flex-col gap-2
|
|
92
|
+
className={cn("flex flex-col gap-2", className)}
|
|
102
93
|
{...props}
|
|
103
94
|
/>
|
|
104
|
-
)
|
|
95
|
+
)
|
|
105
96
|
}
|
|
106
97
|
|
|
107
|
-
function DialogFooter({
|
|
98
|
+
function DialogFooter({
|
|
99
|
+
className,
|
|
100
|
+
showCloseButton = false,
|
|
101
|
+
children,
|
|
102
|
+
...props
|
|
103
|
+
}: React.ComponentProps<"div"> & {
|
|
104
|
+
showCloseButton?: boolean
|
|
105
|
+
}) {
|
|
108
106
|
return (
|
|
109
107
|
<div
|
|
110
108
|
data-slot="dialog-footer"
|
|
111
109
|
className={cn(
|
|
112
|
-
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
110
|
+
"flex flex-col-reverse gap-2 pt-2 sm:flex-row sm:justify-end",
|
|
113
111
|
className
|
|
114
112
|
)}
|
|
115
113
|
{...props}
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
>
|
|
115
|
+
{children}
|
|
116
|
+
{showCloseButton && (
|
|
117
|
+
<DialogPrimitive.Close render={<Button variant="outline" />}>
|
|
118
|
+
Close
|
|
119
|
+
</DialogPrimitive.Close>
|
|
120
|
+
)}
|
|
121
|
+
</div>
|
|
122
|
+
)
|
|
118
123
|
}
|
|
119
124
|
|
|
120
|
-
function DialogTitle({
|
|
121
|
-
className,
|
|
122
|
-
...props
|
|
123
|
-
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
125
|
+
function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
|
|
124
126
|
return (
|
|
125
127
|
<DialogPrimitive.Title
|
|
126
128
|
data-slot="dialog-title"
|
|
127
|
-
className={cn(
|
|
129
|
+
className={cn(
|
|
130
|
+
"font-heading text-base leading-none font-medium",
|
|
131
|
+
className
|
|
132
|
+
)}
|
|
128
133
|
{...props}
|
|
129
134
|
/>
|
|
130
|
-
)
|
|
135
|
+
)
|
|
131
136
|
}
|
|
132
137
|
|
|
133
138
|
function DialogDescription({
|
|
134
139
|
className,
|
|
135
140
|
...props
|
|
136
|
-
}:
|
|
141
|
+
}: DialogPrimitive.Description.Props) {
|
|
137
142
|
return (
|
|
138
143
|
<DialogPrimitive.Description
|
|
139
144
|
data-slot="dialog-description"
|
|
140
|
-
|
|
145
|
+
render={<div />}
|
|
146
|
+
className={cn(
|
|
147
|
+
"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
148
|
+
className
|
|
149
|
+
)}
|
|
141
150
|
{...props}
|
|
142
151
|
/>
|
|
143
|
-
)
|
|
152
|
+
)
|
|
144
153
|
}
|
|
145
154
|
|
|
146
155
|
export {
|
|
@@ -154,4 +163,4 @@ export {
|
|
|
154
163
|
DialogPortal,
|
|
155
164
|
DialogTitle,
|
|
156
165
|
DialogTrigger,
|
|
157
|
-
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { DirectionProvider } from "./direction";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Design System/Direction',
|
|
6
|
+
parameters: { layout: 'centered' },
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
} satisfies Meta;
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof meta>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
render: () => (
|
|
15
|
+
<div className="p-4 w-full h-full flex items-center justify-center">
|
|
16
|
+
<DirectionProvider direction="ltr"><div>LTR Content</div></DirectionProvider>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { axe } from 'jest-axe';
|
|
3
|
+
import { DirectionProvider } from "./direction";
|
|
4
|
+
|
|
5
|
+
describe('Direction Accessibility', () => {
|
|
6
|
+
it('should have no accessibility violations in basic render', async () => {
|
|
7
|
+
const Wrapper = () => (
|
|
8
|
+
<DirectionProvider direction="ltr"><div>LTR Content</div></DirectionProvider>
|
|
9
|
+
);
|
|
10
|
+
const { container } = render(<Wrapper />);
|
|
11
|
+
const results = await axe(container);
|
|
12
|
+
expect(results).toHaveNoViolations();
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, DrawerClose } from "./drawer"; import { Button } from "./button";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Design System/Drawer',
|
|
6
|
+
parameters: { layout: 'centered' },
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
} satisfies Meta;
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof meta>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
render: () => (
|
|
15
|
+
<div className="p-4 w-full h-full flex items-center justify-center">
|
|
16
|
+
<Drawer><DrawerTrigger className="px-4 py-2 border rounded">Open Drawer</DrawerTrigger><DrawerContent><DrawerHeader><DrawerTitle>Are you absolutely sure?</DrawerTitle><DrawerDescription>This action cannot be undone.</DrawerDescription></DrawerHeader><DrawerFooter><Button>Submit</Button><DrawerClose><Button variant="outline">Cancel</Button></DrawerClose></DrawerFooter></DrawerContent></Drawer>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { axe } from 'jest-axe';
|
|
3
|
+
import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, DrawerClose } from "./drawer"; import { Button } from "./button";
|
|
4
|
+
|
|
5
|
+
describe('Drawer Accessibility', () => {
|
|
6
|
+
it('should have no accessibility violations in basic render', async () => {
|
|
7
|
+
const Wrapper = () => (
|
|
8
|
+
<Drawer><DrawerTrigger className="px-4 py-2 border rounded">Open Drawer</DrawerTrigger><DrawerContent><DrawerHeader><DrawerTitle>Are you absolutely sure?</DrawerTitle><DrawerDescription>This action cannot be undone.</DrawerDescription></DrawerHeader><DrawerFooter><Button>Submit</Button><DrawerClose><Button variant="outline">Cancel</Button></DrawerClose></DrawerFooter></DrawerContent></Drawer>
|
|
9
|
+
);
|
|
10
|
+
const { container } = render(<Wrapper />);
|
|
11
|
+
const results = await axe(container);
|
|
12
|
+
expect(results).toHaveNoViolations();
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -1,89 +1,167 @@
|
|
|
1
|
-
"use client"
|
|
1
|
+
"use client"
|
|
2
2
|
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import { Drawer as DrawerPrimitive } from "
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Drawer as DrawerPrimitive } from "@base-ui/react/drawer"
|
|
5
5
|
|
|
6
|
-
import { cn } from "@/lib/utils"
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
type DrawerContextProps = {
|
|
9
|
+
hasSnapPoints: boolean
|
|
10
|
+
modal: DrawerPrimitive.Root.Props["modal"]
|
|
11
|
+
showSwipeHandle: boolean
|
|
12
|
+
swipeDirection: NonNullable<DrawerPrimitive.Root.Props["swipeDirection"]>
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const DrawerContext = React.createContext<DrawerContextProps | null>(null)
|
|
16
|
+
|
|
17
|
+
function useDrawer() {
|
|
18
|
+
const context = React.useContext(DrawerContext)
|
|
19
|
+
|
|
20
|
+
if (!context) {
|
|
21
|
+
throw new Error("useDrawer must be used within a Drawer.")
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return context
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function Drawer({
|
|
28
|
+
modal = true,
|
|
29
|
+
showSwipeHandle = false,
|
|
30
|
+
snapPoints,
|
|
31
|
+
swipeDirection = "down",
|
|
16
32
|
...props
|
|
17
|
-
}:
|
|
33
|
+
}: DrawerPrimitive.Root.Props & {
|
|
34
|
+
showSwipeHandle?: boolean
|
|
35
|
+
}) {
|
|
36
|
+
const hasSnapPoints = snapPoints != null && snapPoints.length > 0
|
|
37
|
+
const contextValue = React.useMemo(
|
|
38
|
+
() => ({ hasSnapPoints, modal, showSwipeHandle, swipeDirection }),
|
|
39
|
+
[hasSnapPoints, modal, showSwipeHandle, swipeDirection]
|
|
40
|
+
)
|
|
41
|
+
|
|
18
42
|
return (
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
43
|
+
<DrawerContext.Provider value={contextValue}>
|
|
44
|
+
<DrawerPrimitive.Root
|
|
45
|
+
data-slot="drawer"
|
|
46
|
+
modal={modal}
|
|
47
|
+
snapPoints={snapPoints}
|
|
48
|
+
swipeDirection={swipeDirection}
|
|
49
|
+
{...props}
|
|
50
|
+
/>
|
|
51
|
+
</DrawerContext.Provider>
|
|
52
|
+
)
|
|
25
53
|
}
|
|
26
54
|
|
|
27
|
-
function
|
|
28
|
-
...props
|
|
29
|
-
}
|
|
30
|
-
|
|
55
|
+
function DrawerTrigger({ ...props }: DrawerPrimitive.Trigger.Props) {
|
|
56
|
+
return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function DrawerPortal({ ...props }: DrawerPrimitive.Portal.Props) {
|
|
60
|
+
return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function DrawerClose({ ...props }: DrawerPrimitive.Close.Props) {
|
|
64
|
+
return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />
|
|
31
65
|
}
|
|
32
66
|
|
|
33
|
-
function
|
|
67
|
+
function DrawerOverlay({
|
|
34
68
|
className,
|
|
35
69
|
...props
|
|
36
|
-
}:
|
|
70
|
+
}: DrawerPrimitive.Backdrop.Props) {
|
|
37
71
|
return (
|
|
38
|
-
<DrawerPrimitive.
|
|
39
|
-
data-slot="drawer-
|
|
40
|
-
className={cn(
|
|
72
|
+
<DrawerPrimitive.Backdrop
|
|
73
|
+
data-slot="drawer-overlay"
|
|
74
|
+
className={cn(
|
|
75
|
+
"fixed inset-0 z-50 min-h-dvh bg-black/10 opacity-[max(var(--drawer-overlay-min-opacity,0),calc(1-var(--drawer-swipe-progress)))] transition-opacity duration-450 ease-[cubic-bezier(0.32,0.72,0,1)] select-none data-ending-style:pointer-events-none data-ending-style:opacity-0 data-ending-style:duration-[calc(var(--drawer-swipe-strength)*400ms)] data-snap-points:[--drawer-overlay-min-opacity:0.5] data-starting-style:opacity-0 data-swiping:duration-0 supports-backdrop-filter:backdrop-blur-xs supports-[-webkit-touch-callout:none]:absolute",
|
|
76
|
+
className
|
|
77
|
+
)}
|
|
41
78
|
{...props}
|
|
42
79
|
/>
|
|
43
|
-
)
|
|
80
|
+
)
|
|
44
81
|
}
|
|
45
82
|
|
|
46
|
-
function
|
|
83
|
+
function DrawerSwipeHandle({
|
|
47
84
|
className,
|
|
48
85
|
...props
|
|
49
|
-
}: React.ComponentProps<
|
|
86
|
+
}: React.ComponentProps<"div">) {
|
|
50
87
|
return (
|
|
51
|
-
<
|
|
52
|
-
data-slot="drawer-
|
|
88
|
+
<div
|
|
89
|
+
data-slot="drawer-swipe-handle"
|
|
90
|
+
aria-hidden="true"
|
|
53
91
|
className={cn(
|
|
54
|
-
"data-[
|
|
92
|
+
"relative z-10 flex shrink-0 cursor-grab transition-opacity duration-200 group-data-nested-drawer-open/drawer-popup:opacity-0 group-data-nested-drawer-swiping/drawer-popup:opacity-100 group-data-[swipe-axis=x]/drawer-popup:h-full group-data-[swipe-axis=x]/drawer-popup:w-3 group-data-[swipe-axis=x]/drawer-popup:items-center group-data-[swipe-axis=y]/drawer-popup:h-3 group-data-[swipe-axis=y]/drawer-popup:w-full group-data-[swipe-axis=y]/drawer-popup:justify-center group-data-[swipe-direction=down]/drawer-popup:items-end group-data-[swipe-direction=left]/drawer-popup:order-last group-data-[swipe-direction=left]/drawer-popup:justify-start group-data-[swipe-direction=right]/drawer-popup:justify-end group-data-[swipe-direction=up]/drawer-popup:order-last group-data-[swipe-direction=up]/drawer-popup:items-start after:block after:shrink-0 after:rounded-full after:bg-muted group-data-[swipe-axis=x]/drawer-popup:after:h-24 group-data-[swipe-axis=x]/drawer-popup:after:w-1 group-data-[swipe-axis=y]/drawer-popup:after:h-1 group-data-[swipe-axis=y]/drawer-popup:after:w-24 active:cursor-grabbing",
|
|
55
93
|
className
|
|
56
94
|
)}
|
|
57
95
|
{...props}
|
|
58
96
|
/>
|
|
59
|
-
)
|
|
97
|
+
)
|
|
60
98
|
}
|
|
61
99
|
|
|
62
100
|
function DrawerContent({
|
|
63
101
|
className,
|
|
64
102
|
children,
|
|
65
103
|
...props
|
|
66
|
-
}:
|
|
104
|
+
}: DrawerPrimitive.Popup.Props) {
|
|
105
|
+
const { hasSnapPoints, modal, showSwipeHandle, swipeDirection } = useDrawer()
|
|
106
|
+
const swipeAxis =
|
|
107
|
+
swipeDirection === "down" || swipeDirection === "up" ? "y" : "x"
|
|
108
|
+
|
|
67
109
|
return (
|
|
68
110
|
<DrawerPortal data-slot="drawer-portal">
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
|
|
77
|
-
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm",
|
|
78
|
-
className
|
|
79
|
-
)}
|
|
80
|
-
{...props}
|
|
111
|
+
{modal === true && (
|
|
112
|
+
<DrawerOverlay data-snap-points={hasSnapPoints ? "" : undefined} />
|
|
113
|
+
)}
|
|
114
|
+
<DrawerPrimitive.Viewport
|
|
115
|
+
data-slot="drawer-viewport"
|
|
116
|
+
data-modal={modal}
|
|
117
|
+
className="pointer-events-none fixed inset-0 z-50 select-none data-[modal=true]:pointer-events-auto"
|
|
81
118
|
>
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
|
|
119
|
+
<DrawerPrimitive.Popup
|
|
120
|
+
data-slot="drawer-popup"
|
|
121
|
+
data-swipe-axis={swipeAxis}
|
|
122
|
+
data-snap-points={hasSnapPoints ? "" : undefined}
|
|
123
|
+
className={cn(
|
|
124
|
+
// Base.
|
|
125
|
+
"group/drawer-popup pointer-events-auto fixed z-50 m-(--drawer-inset,0px) flex h-(--drawer-content-height) max-h-(--drawer-content-max-height,none) min-h-0 w-(--drawer-content-width,auto) transform-[translate3d(var(--translate-x,0px),var(--translate-y,0px),0)_scale(var(--stack-scale))] flex-col bg-popover text-sm text-popover-foreground transition-[transform,height,opacity,filter] duration-450 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-transform outline-none select-none [interpolate-size:allow-keywords] data-[swipe-direction=down]:rounded-t-xl data-[swipe-direction=down]:border-t data-[swipe-direction=left]:rounded-r-xl data-[swipe-direction=left]:border-r data-[swipe-direction=right]:rounded-l-xl data-[swipe-direction=right]:border-l data-[swipe-direction=up]:rounded-b-xl data-[swipe-direction=up]:border-b",
|
|
126
|
+
// Nested.
|
|
127
|
+
"data-nested-drawer-open:overflow-hidden data-nested-drawer-open:brightness-95",
|
|
128
|
+
// Bleed.
|
|
129
|
+
"after:pointer-events-none after:absolute after:bg-(--drawer-bleed-background,var(--color-popover)) data-[swipe-axis=x]:after:inset-y-0 data-[swipe-axis=x]:after:w-(--bleed) data-[swipe-axis=y]:after:inset-x-0 data-[swipe-axis=y]:after:h-(--bleed) data-[swipe-direction=down]:after:top-full data-[swipe-direction=left]:after:right-full data-[swipe-direction=right]:after:left-full data-[swipe-direction=up]:after:bottom-full",
|
|
130
|
+
// Sizing.
|
|
131
|
+
"[--drawer-content-height:var(--drawer-height,auto)] data-[swipe-axis=x]:[--drawer-content-width:75%] data-[swipe-axis=y]:[--drawer-content-max-height:calc(100dvh-6rem)] data-[swipe-axis=y]:data-snap-points:[--drawer-content-height:100dvh] data-[swipe-axis=x]:sm:[--drawer-content-width:24rem]",
|
|
132
|
+
// Stack.
|
|
133
|
+
"[--bleed:3rem] [--peek:1rem] [--stack-height:var(--drawer-frontmost-height,var(--drawer-height,0px))] [--stack-peek-offset:max(0px,calc((var(--nested-drawers)-var(--stack-progress))*var(--peek)))] [--stack-progress:clamp(0,var(--drawer-swipe-progress),1)] [--stack-scale-base:max(0,calc(1-(var(--nested-drawers)*var(--stack-step))))] [--stack-scale:clamp(0,calc(var(--stack-scale-base)+(var(--stack-step)*var(--stack-progress))),1)] [--stack-shrink:calc(1-var(--stack-scale))] [--stack-step:0.05]",
|
|
134
|
+
// Transitions.
|
|
135
|
+
"data-ending-style:transform-(--closed-transform) data-ending-style:opacity-[0.9999] data-ending-style:duration-[calc(var(--drawer-swipe-strength)*400ms)] data-nested-drawer-swiping:duration-0 data-ending-style:data-nested-drawer-swiping:duration-[calc(var(--drawer-swipe-strength)*400ms)] data-starting-style:transform-(--closed-transform) data-swiping:duration-0 data-ending-style:data-swiping:duration-[calc(var(--drawer-swipe-strength)*400ms)]",
|
|
136
|
+
// Axis: y.
|
|
137
|
+
"data-[swipe-axis=y]:inset-x-0 data-[swipe-axis=y]:data-nested-drawer-open:h-(--stack-height)",
|
|
138
|
+
// Axis: x.
|
|
139
|
+
"data-[swipe-axis=x]:inset-y-0 data-[swipe-axis=x]:flex-row",
|
|
140
|
+
// Direction: down.
|
|
141
|
+
"data-[swipe-direction=down]:bottom-0 data-[swipe-direction=down]:origin-bottom data-[swipe-direction=down]:[--closed-transform:translate3d(0,calc(100%+var(--drawer-inset,0px)+2px),0)] data-[swipe-direction=down]:[--translate-y:calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-y)-var(--stack-peek-offset)-(var(--stack-shrink)*var(--stack-height)))]",
|
|
142
|
+
// Direction: up.
|
|
143
|
+
"data-[swipe-direction=up]:top-0 data-[swipe-direction=up]:origin-top data-[swipe-direction=up]:[--closed-transform:translate3d(0,calc(-100%-var(--drawer-inset,0px)-2px),0)] data-[swipe-direction=up]:[--translate-y:calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-y)+var(--stack-peek-offset)+(var(--stack-shrink)*var(--stack-height)))]",
|
|
144
|
+
// Direction: left.
|
|
145
|
+
"data-[swipe-direction=left]:left-0 data-[swipe-direction=left]:origin-left data-[swipe-direction=left]:[--closed-transform:translate3d(calc(-100%-var(--drawer-inset,0px)-2px),0,0)] data-[swipe-direction=left]:[--translate-x:calc(var(--drawer-swipe-movement-x)+var(--stack-peek-offset)+(var(--stack-shrink)*100%))]",
|
|
146
|
+
// Direction: right.
|
|
147
|
+
"data-[swipe-direction=right]:right-0 data-[swipe-direction=right]:origin-right data-[swipe-direction=right]:[--closed-transform:translate3d(calc(100%+var(--drawer-inset,0px)+2px),0,0)] data-[swipe-direction=right]:[--translate-x:calc(var(--drawer-swipe-movement-x)-var(--stack-peek-offset)-(var(--stack-shrink)*100%))]",
|
|
148
|
+
className
|
|
149
|
+
)}
|
|
150
|
+
{...props}
|
|
151
|
+
>
|
|
152
|
+
{showSwipeHandle && <DrawerSwipeHandle />}
|
|
153
|
+
<DrawerPrimitive.Content
|
|
154
|
+
data-slot="drawer-content"
|
|
155
|
+
className={cn(
|
|
156
|
+
"flex min-h-0 flex-1 flex-col overflow-hidden overscroll-contain rounded-[inherit] transition-opacity duration-300 ease-[cubic-bezier(0.45,1.005,0,1.005)] select-text group-data-nested-drawer-open/drawer-popup:opacity-0 group-data-nested-drawer-swiping/drawer-popup:opacity-100 group-data-swiping/drawer-popup:select-none"
|
|
157
|
+
)}
|
|
158
|
+
>
|
|
159
|
+
{children}
|
|
160
|
+
</DrawerPrimitive.Content>
|
|
161
|
+
</DrawerPrimitive.Popup>
|
|
162
|
+
</DrawerPrimitive.Viewport>
|
|
85
163
|
</DrawerPortal>
|
|
86
|
-
)
|
|
164
|
+
)
|
|
87
165
|
}
|
|
88
166
|
|
|
89
167
|
function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
@@ -91,54 +169,55 @@ function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
91
169
|
<div
|
|
92
170
|
data-slot="drawer-header"
|
|
93
171
|
className={cn(
|
|
94
|
-
"flex flex-col gap-0.5 p-4
|
|
172
|
+
"flex shrink-0 flex-col gap-0.5 p-4 pb-0 group-data-[swipe-axis=y]/drawer-popup:text-center md:gap-0.5 md:text-left",
|
|
95
173
|
className
|
|
96
174
|
)}
|
|
97
175
|
{...props}
|
|
98
176
|
/>
|
|
99
|
-
)
|
|
177
|
+
)
|
|
100
178
|
}
|
|
101
179
|
|
|
102
180
|
function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
103
181
|
return (
|
|
104
182
|
<div
|
|
105
183
|
data-slot="drawer-footer"
|
|
106
|
-
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
|
184
|
+
className={cn("mt-auto flex shrink-0 flex-col gap-2 p-4 pt-0", className)}
|
|
107
185
|
{...props}
|
|
108
186
|
/>
|
|
109
|
-
)
|
|
187
|
+
)
|
|
110
188
|
}
|
|
111
189
|
|
|
112
|
-
function DrawerTitle({
|
|
113
|
-
className,
|
|
114
|
-
...props
|
|
115
|
-
}: React.ComponentProps<typeof DrawerPrimitive.Title>) {
|
|
190
|
+
function DrawerTitle({ className, ...props }: DrawerPrimitive.Title.Props) {
|
|
116
191
|
return (
|
|
117
192
|
<DrawerPrimitive.Title
|
|
118
193
|
data-slot="drawer-title"
|
|
119
|
-
className={cn(
|
|
194
|
+
className={cn(
|
|
195
|
+
"font-heading text-base font-medium text-foreground",
|
|
196
|
+
className
|
|
197
|
+
)}
|
|
120
198
|
{...props}
|
|
121
199
|
/>
|
|
122
|
-
)
|
|
200
|
+
)
|
|
123
201
|
}
|
|
124
202
|
|
|
125
203
|
function DrawerDescription({
|
|
126
204
|
className,
|
|
127
205
|
...props
|
|
128
|
-
}:
|
|
206
|
+
}: DrawerPrimitive.Description.Props) {
|
|
129
207
|
return (
|
|
130
208
|
<DrawerPrimitive.Description
|
|
131
209
|
data-slot="drawer-description"
|
|
132
|
-
className={cn("text-
|
|
210
|
+
className={cn("text-sm text-balance text-muted-foreground", className)}
|
|
133
211
|
{...props}
|
|
134
212
|
/>
|
|
135
|
-
)
|
|
213
|
+
)
|
|
136
214
|
}
|
|
137
215
|
|
|
138
216
|
export {
|
|
139
217
|
Drawer,
|
|
140
218
|
DrawerPortal,
|
|
141
219
|
DrawerOverlay,
|
|
220
|
+
DrawerSwipeHandle,
|
|
142
221
|
DrawerTrigger,
|
|
143
222
|
DrawerClose,
|
|
144
223
|
DrawerContent,
|
|
@@ -146,4 +225,4 @@ export {
|
|
|
146
225
|
DrawerFooter,
|
|
147
226
|
DrawerTitle,
|
|
148
227
|
DrawerDescription,
|
|
149
|
-
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup } from "./dropdown-menu";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Design System/DropdownMenu',
|
|
6
|
+
parameters: { layout: 'centered' },
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
} satisfies Meta;
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof meta>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
render: () => (
|
|
15
|
+
<div className="p-4 w-full h-full flex items-center justify-center">
|
|
16
|
+
<DropdownMenu><DropdownMenuTrigger className="px-4 py-2 border rounded">Open</DropdownMenuTrigger><DropdownMenuContent><DropdownMenuLabel>My Account</DropdownMenuLabel><DropdownMenuSeparator /><DropdownMenuGroup><DropdownMenuItem>Profile</DropdownMenuItem><DropdownMenuItem>Billing</DropdownMenuItem></DropdownMenuGroup></DropdownMenuContent></DropdownMenu>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { axe } from 'jest-axe';
|
|
3
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup } from "./dropdown-menu";
|
|
4
|
+
|
|
5
|
+
describe('DropdownMenu Accessibility', () => {
|
|
6
|
+
it('should have no accessibility violations in basic render', async () => {
|
|
7
|
+
const Wrapper = () => (
|
|
8
|
+
<DropdownMenu><DropdownMenuTrigger className="px-4 py-2 border rounded">Open</DropdownMenuTrigger><DropdownMenuContent><DropdownMenuLabel>My Account</DropdownMenuLabel><DropdownMenuSeparator /><DropdownMenuGroup><DropdownMenuItem>Profile</DropdownMenuItem><DropdownMenuItem>Billing</DropdownMenuItem></DropdownMenuGroup></DropdownMenuContent></DropdownMenu>
|
|
9
|
+
);
|
|
10
|
+
const { container } = render(<Wrapper />);
|
|
11
|
+
const results = await axe(container);
|
|
12
|
+
expect(results).toHaveNoViolations();
|
|
13
|
+
});
|
|
14
|
+
});
|