@inspirare/design-system 0.0.23 → 0.0.25
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 +116 -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 +38 -37
- 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 +32 -0
- package/src/components/ui/select.tsx +172 -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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { axe } from 'jest-axe';
|
|
3
|
+
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "./select";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
describe('Select Accessibility', () => {
|
|
7
|
+
it('should have no accessibility violations in basic render', async () => {
|
|
8
|
+
const Wrapper = () => (
|
|
9
|
+
<Select><SelectTrigger aria-label="Select a theme" className="w-[180px]"><SelectValue placeholder="Theme" /></SelectTrigger><SelectContent><SelectItem value="light">Light</SelectItem><SelectItem value="dark">Dark</SelectItem><SelectItem value="system">System</SelectItem></SelectContent></Select>
|
|
10
|
+
);
|
|
11
|
+
const { container } = render(<Wrapper />);
|
|
12
|
+
const results = await axe(container);
|
|
13
|
+
expect(results).toHaveNoViolations();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should display the default label instead of the value on initial render', () => {
|
|
17
|
+
const Wrapper = () => (
|
|
18
|
+
<Select defaultValue="dark">
|
|
19
|
+
<SelectTrigger aria-label="Select a theme" className="w-[180px]">
|
|
20
|
+
<SelectValue placeholder="Theme" />
|
|
21
|
+
</SelectTrigger>
|
|
22
|
+
<SelectContent>
|
|
23
|
+
<SelectItem value="light">Light</SelectItem>
|
|
24
|
+
<SelectItem value="dark">Dark Theme</SelectItem>
|
|
25
|
+
<SelectItem value="system">System</SelectItem>
|
|
26
|
+
</SelectContent>
|
|
27
|
+
</Select>
|
|
28
|
+
);
|
|
29
|
+
const { container } = render(<Wrapper />);
|
|
30
|
+
expect(container.textContent).toContain('Dark Theme');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -1,27 +1,95 @@
|
|
|
1
|
-
"use client"
|
|
1
|
+
"use client"
|
|
2
2
|
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import
|
|
5
|
-
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Select as SelectPrimitive } from "@base-ui/react/select"
|
|
6
5
|
|
|
7
|
-
import { cn } from "@/lib/utils"
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react"
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
9
|
+
const SelectContext = React.createContext<{
|
|
10
|
+
registerLabel: (val: any, label: string) => void;
|
|
11
|
+
getLabel: (val: any) => string | undefined;
|
|
12
|
+
} | null>(null);
|
|
14
13
|
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
function Select({ children, ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
|
15
|
+
const [dynamicLabels, setDynamicLabels] = React.useState<Record<string, string>>({});
|
|
16
|
+
|
|
17
|
+
const staticLabels = React.useMemo(() => {
|
|
18
|
+
const result: Record<string, string> = {};
|
|
19
|
+
const extract = (node: React.ReactNode) => {
|
|
20
|
+
React.Children.forEach(node, (child) => {
|
|
21
|
+
if (!React.isValidElement(child)) return;
|
|
22
|
+
if ((child as any).props && (child as any).props.value !== undefined) {
|
|
23
|
+
if ((child as any).props.children) {
|
|
24
|
+
let label = "";
|
|
25
|
+
React.Children.forEach((child as any).props.children, (grandChild) => {
|
|
26
|
+
if (typeof grandChild === "string" || typeof grandChild === "number") {
|
|
27
|
+
label += grandChild;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
if (label) result[(child as any).props.value] = label;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if ((child as any).props && (child as any).props.children) {
|
|
34
|
+
extract((child as any).props.children);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
extract(children);
|
|
39
|
+
return result;
|
|
40
|
+
}, [children]);
|
|
41
|
+
|
|
42
|
+
const labels = { ...staticLabels, ...dynamicLabels };
|
|
43
|
+
|
|
44
|
+
const registerLabel = React.useCallback((val: any, label: string) => {
|
|
45
|
+
setDynamicLabels((prev) => {
|
|
46
|
+
if (prev[val] === label) return prev;
|
|
47
|
+
return { ...prev, [val]: label };
|
|
48
|
+
});
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
const getLabel = React.useCallback((val: any) => labels[val], [labels]);
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<SelectContext.Provider value={{ registerLabel, getLabel }}>
|
|
55
|
+
<SelectPrimitive.Root {...props}>
|
|
56
|
+
{children}
|
|
57
|
+
</SelectPrimitive.Root>
|
|
58
|
+
</SelectContext.Provider>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {
|
|
62
|
+
return (
|
|
63
|
+
<SelectPrimitive.Group
|
|
64
|
+
data-slot="select-group"
|
|
65
|
+
className={cn("scroll-my-1 p-1", className)}
|
|
66
|
+
{...props}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
19
69
|
}
|
|
20
70
|
|
|
21
|
-
function SelectValue({
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return
|
|
71
|
+
function SelectValue({ className, children, ...props }: SelectPrimitive.Value.Props) {
|
|
72
|
+
const ctx = React.useContext(SelectContext);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<SelectPrimitive.Value
|
|
76
|
+
data-slot="select-value"
|
|
77
|
+
className={cn("flex flex-1 text-left", className)}
|
|
78
|
+
{...props}
|
|
79
|
+
>
|
|
80
|
+
{children ? children : (val: any) => {
|
|
81
|
+
if (!val) return null;
|
|
82
|
+
if (ctx) {
|
|
83
|
+
if (Array.isArray(val)) {
|
|
84
|
+
return val.map(v => ctx.getLabel(v) || v).join(', ');
|
|
85
|
+
}
|
|
86
|
+
const label = ctx.getLabel(val);
|
|
87
|
+
if (label) return label;
|
|
88
|
+
}
|
|
89
|
+
return val;
|
|
90
|
+
}}
|
|
91
|
+
</SelectPrimitive.Value>
|
|
92
|
+
)
|
|
25
93
|
}
|
|
26
94
|
|
|
27
95
|
function SelectTrigger({
|
|
@@ -29,146 +97,172 @@ function SelectTrigger({
|
|
|
29
97
|
size = "default",
|
|
30
98
|
children,
|
|
31
99
|
...props
|
|
32
|
-
}:
|
|
33
|
-
size?: "sm" | "default"
|
|
100
|
+
}: SelectPrimitive.Trigger.Props & {
|
|
101
|
+
size?: "sm" | "default"
|
|
34
102
|
}) {
|
|
35
103
|
return (
|
|
36
104
|
<SelectPrimitive.Trigger
|
|
37
105
|
data-slot="select-trigger"
|
|
38
106
|
data-size={size}
|
|
39
107
|
className={cn(
|
|
40
|
-
"
|
|
108
|
+
"flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
41
109
|
className
|
|
42
110
|
)}
|
|
43
111
|
{...props}
|
|
44
112
|
>
|
|
45
113
|
{children}
|
|
46
|
-
<SelectPrimitive.Icon
|
|
47
|
-
|
|
48
|
-
|
|
114
|
+
<SelectPrimitive.Icon
|
|
115
|
+
render={
|
|
116
|
+
<ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
|
|
117
|
+
}
|
|
118
|
+
/>
|
|
49
119
|
</SelectPrimitive.Trigger>
|
|
50
|
-
)
|
|
120
|
+
)
|
|
51
121
|
}
|
|
52
122
|
|
|
53
123
|
function SelectContent({
|
|
54
124
|
className,
|
|
55
125
|
children,
|
|
56
|
-
|
|
126
|
+
side = "bottom",
|
|
127
|
+
sideOffset = 4,
|
|
128
|
+
align = "center",
|
|
129
|
+
alignOffset = 0,
|
|
130
|
+
alignItemWithTrigger = true,
|
|
57
131
|
...props
|
|
58
|
-
}:
|
|
132
|
+
}: SelectPrimitive.Popup.Props &
|
|
133
|
+
Pick<
|
|
134
|
+
SelectPrimitive.Positioner.Props,
|
|
135
|
+
"align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger"
|
|
136
|
+
>) {
|
|
59
137
|
return (
|
|
60
138
|
<SelectPrimitive.Portal>
|
|
61
|
-
<SelectPrimitive.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
)}
|
|
69
|
-
position={position}
|
|
70
|
-
{...props}
|
|
139
|
+
<SelectPrimitive.Positioner
|
|
140
|
+
side={side}
|
|
141
|
+
sideOffset={sideOffset}
|
|
142
|
+
align={align}
|
|
143
|
+
alignOffset={alignOffset}
|
|
144
|
+
alignItemWithTrigger={alignItemWithTrigger}
|
|
145
|
+
className="isolate z-50"
|
|
71
146
|
>
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
|
78
|
-
)}
|
|
147
|
+
<SelectPrimitive.Popup
|
|
148
|
+
data-slot="select-content"
|
|
149
|
+
data-align-trigger={alignItemWithTrigger}
|
|
150
|
+
className={cn("relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 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", className )}
|
|
151
|
+
{...props}
|
|
79
152
|
>
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
153
|
+
<SelectScrollUpButton />
|
|
154
|
+
<SelectPrimitive.List>{children}</SelectPrimitive.List>
|
|
155
|
+
<SelectScrollDownButton />
|
|
156
|
+
</SelectPrimitive.Popup>
|
|
157
|
+
</SelectPrimitive.Positioner>
|
|
84
158
|
</SelectPrimitive.Portal>
|
|
85
|
-
)
|
|
159
|
+
)
|
|
86
160
|
}
|
|
87
161
|
|
|
88
162
|
function SelectLabel({
|
|
89
163
|
className,
|
|
90
164
|
...props
|
|
91
|
-
}:
|
|
165
|
+
}: SelectPrimitive.GroupLabel.Props) {
|
|
92
166
|
return (
|
|
93
|
-
<SelectPrimitive.
|
|
167
|
+
<SelectPrimitive.GroupLabel
|
|
94
168
|
data-slot="select-label"
|
|
95
|
-
className={cn("
|
|
169
|
+
className={cn("px-1.5 py-1 text-xs text-muted-foreground", className)}
|
|
96
170
|
{...props}
|
|
97
171
|
/>
|
|
98
|
-
)
|
|
172
|
+
)
|
|
99
173
|
}
|
|
100
174
|
|
|
101
175
|
function SelectItem({
|
|
102
176
|
className,
|
|
103
177
|
children,
|
|
178
|
+
value,
|
|
104
179
|
...props
|
|
105
|
-
}:
|
|
180
|
+
}: SelectPrimitive.Item.Props) {
|
|
181
|
+
const ctx = React.useContext(SelectContext);
|
|
182
|
+
const textRef = React.useRef<HTMLDivElement>(null);
|
|
183
|
+
|
|
184
|
+
React.useEffect(() => {
|
|
185
|
+
if (value !== undefined && textRef.current && ctx) {
|
|
186
|
+
const text = textRef.current.textContent;
|
|
187
|
+
if (text) {
|
|
188
|
+
ctx.registerLabel(value, text.trim());
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}, [value, ctx, children]);
|
|
192
|
+
|
|
106
193
|
return (
|
|
107
194
|
<SelectPrimitive.Item
|
|
195
|
+
value={value}
|
|
108
196
|
data-slot="select-item"
|
|
109
197
|
className={cn(
|
|
110
|
-
"
|
|
198
|
+
"relative flex w-full cursor-pointer items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
111
199
|
className
|
|
112
200
|
)}
|
|
113
201
|
{...props}
|
|
114
202
|
>
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
203
|
+
<SelectPrimitive.ItemText ref={textRef} className="flex flex-1 shrink-0 gap-2 whitespace-nowrap">
|
|
204
|
+
{children}
|
|
205
|
+
</SelectPrimitive.ItemText>
|
|
206
|
+
<SelectPrimitive.ItemIndicator
|
|
207
|
+
render={
|
|
208
|
+
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
|
|
209
|
+
}
|
|
210
|
+
>
|
|
211
|
+
<CheckIcon className="pointer-events-none" />
|
|
212
|
+
</SelectPrimitive.ItemIndicator>
|
|
121
213
|
</SelectPrimitive.Item>
|
|
122
|
-
)
|
|
214
|
+
)
|
|
123
215
|
}
|
|
124
216
|
|
|
125
217
|
function SelectSeparator({
|
|
126
218
|
className,
|
|
127
219
|
...props
|
|
128
|
-
}:
|
|
220
|
+
}: SelectPrimitive.Separator.Props) {
|
|
129
221
|
return (
|
|
130
222
|
<SelectPrimitive.Separator
|
|
131
223
|
data-slot="select-separator"
|
|
132
|
-
className={cn("
|
|
224
|
+
className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
|
|
133
225
|
{...props}
|
|
134
226
|
/>
|
|
135
|
-
)
|
|
227
|
+
)
|
|
136
228
|
}
|
|
137
229
|
|
|
138
230
|
function SelectScrollUpButton({
|
|
139
231
|
className,
|
|
140
232
|
...props
|
|
141
|
-
}: React.ComponentProps<typeof SelectPrimitive.
|
|
233
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>) {
|
|
142
234
|
return (
|
|
143
|
-
<SelectPrimitive.
|
|
235
|
+
<SelectPrimitive.ScrollUpArrow
|
|
144
236
|
data-slot="select-scroll-up-button"
|
|
145
237
|
className={cn(
|
|
146
|
-
"flex cursor-pointer items-center justify-center py-1",
|
|
238
|
+
"top-0 z-10 flex w-full cursor-pointer items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
|
|
147
239
|
className
|
|
148
240
|
)}
|
|
149
241
|
{...props}
|
|
150
242
|
>
|
|
151
|
-
<ChevronUpIcon
|
|
152
|
-
|
|
153
|
-
|
|
243
|
+
<ChevronUpIcon
|
|
244
|
+
/>
|
|
245
|
+
</SelectPrimitive.ScrollUpArrow>
|
|
246
|
+
)
|
|
154
247
|
}
|
|
155
248
|
|
|
156
249
|
function SelectScrollDownButton({
|
|
157
250
|
className,
|
|
158
251
|
...props
|
|
159
|
-
}: React.ComponentProps<typeof SelectPrimitive.
|
|
252
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>) {
|
|
160
253
|
return (
|
|
161
|
-
<SelectPrimitive.
|
|
254
|
+
<SelectPrimitive.ScrollDownArrow
|
|
162
255
|
data-slot="select-scroll-down-button"
|
|
163
256
|
className={cn(
|
|
164
|
-
"flex cursor-pointer items-center justify-center py-1",
|
|
257
|
+
"bottom-0 z-10 flex w-full cursor-pointer items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
|
|
165
258
|
className
|
|
166
259
|
)}
|
|
167
260
|
{...props}
|
|
168
261
|
>
|
|
169
|
-
<ChevronDownIcon
|
|
170
|
-
|
|
171
|
-
|
|
262
|
+
<ChevronDownIcon
|
|
263
|
+
/>
|
|
264
|
+
</SelectPrimitive.ScrollDownArrow>
|
|
265
|
+
)
|
|
172
266
|
}
|
|
173
267
|
|
|
174
268
|
export {
|
|
@@ -182,4 +276,4 @@ export {
|
|
|
182
276
|
SelectSeparator,
|
|
183
277
|
SelectTrigger,
|
|
184
278
|
SelectValue,
|
|
185
|
-
}
|
|
279
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Separator } from "./separator";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Design System/Separator',
|
|
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
|
+
<div><div className="space-y-1"><h4 className="text-sm font-medium leading-none">Radix Primitives</h4><p className="text-sm text-muted-foreground">An open-source UI component library.</p></div><Separator className="my-4" /><div className="flex h-5 items-center space-x-4 text-sm"><div>Blog</div><Separator orientation="vertical" /><div>Docs</div></div></div>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { axe } from 'jest-axe';
|
|
3
|
+
import { Separator } from "./separator";
|
|
4
|
+
|
|
5
|
+
describe('Separator Accessibility', () => {
|
|
6
|
+
it('should have no accessibility violations in basic render', async () => {
|
|
7
|
+
const Wrapper = () => (
|
|
8
|
+
<div><div className="space-y-1"><h4 className="text-sm font-medium leading-none">Radix Primitives</h4><p className="text-sm text-muted-foreground">An open-source UI component library.</p></div><Separator className="my-4" /><div className="flex h-5 items-center space-x-4 text-sm"><div>Blog</div><Separator orientation="vertical" /><div>Docs</div></div></div>
|
|
9
|
+
);
|
|
10
|
+
const { container } = render(<Wrapper />);
|
|
11
|
+
const results = await axe(container);
|
|
12
|
+
expect(results).toHaveNoViolations();
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
"use client"
|
|
1
|
+
"use client"
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
3
|
+
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
|
|
5
4
|
|
|
6
|
-
import { cn } from "@/lib/utils"
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
7
6
|
|
|
8
7
|
function Separator({
|
|
9
8
|
className,
|
|
10
9
|
orientation = "horizontal",
|
|
11
|
-
decorative = true,
|
|
12
10
|
...props
|
|
13
|
-
}:
|
|
11
|
+
}: SeparatorPrimitive.Props) {
|
|
14
12
|
return (
|
|
15
|
-
<SeparatorPrimitive
|
|
13
|
+
<SeparatorPrimitive
|
|
16
14
|
data-slot="separator"
|
|
17
|
-
decorative={decorative}
|
|
18
15
|
orientation={orientation}
|
|
19
16
|
className={cn(
|
|
20
|
-
"bg-border
|
|
17
|
+
"shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
|
|
21
18
|
className
|
|
22
19
|
)}
|
|
23
20
|
{...props}
|
|
24
21
|
/>
|
|
25
|
-
)
|
|
22
|
+
)
|
|
26
23
|
}
|
|
27
24
|
|
|
28
|
-
export { Separator }
|
|
25
|
+
export { Separator }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription } from "./sheet";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Design System/Sheet',
|
|
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
|
+
<Sheet><SheetTrigger className="px-4 py-2 border rounded">Open</SheetTrigger><SheetContent><SheetHeader><SheetTitle>Are you sure?</SheetTitle><SheetDescription>This action cannot be undone.</SheetDescription></SheetHeader></SheetContent></Sheet>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { axe } from 'jest-axe';
|
|
3
|
+
import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription } from "./sheet";
|
|
4
|
+
|
|
5
|
+
describe('Sheet Accessibility', () => {
|
|
6
|
+
it('should have no accessibility violations in basic render', async () => {
|
|
7
|
+
const Wrapper = () => (
|
|
8
|
+
<Sheet><SheetTrigger className="px-4 py-2 border rounded">Open</SheetTrigger><SheetContent><SheetHeader><SheetTitle>Are you sure?</SheetTitle><SheetDescription>This action cannot be undone.</SheetDescription></SheetHeader></SheetContent></Sheet>
|
|
9
|
+
);
|
|
10
|
+
const { container } = render(<Wrapper />);
|
|
11
|
+
const results = await axe(container);
|
|
12
|
+
expect(results).toHaveNoViolations();
|
|
13
|
+
});
|
|
14
|
+
});
|