@djangocfg/ui-core 2.1.119 → 2.1.121
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/package.json +8 -5
- package/src/components/accordion.story.tsx +110 -0
- package/src/components/alert-dialog.story.tsx +104 -0
- package/src/components/alert.story.tsx +77 -0
- package/src/components/aspect-ratio.story.tsx +94 -0
- package/src/components/avatar.story.tsx +115 -0
- package/src/components/badge.story.tsx +56 -0
- package/src/components/button-download.story.tsx +112 -0
- package/src/components/button-group.story.tsx +79 -0
- package/src/components/button.story.tsx +116 -0
- package/src/components/calendar.story.tsx +126 -0
- package/src/components/card.story.tsx +105 -0
- package/src/components/carousel.story.tsx +122 -0
- package/src/components/checkbox.story.tsx +89 -0
- package/src/components/collapsible.story.tsx +133 -0
- package/src/components/combobox.story.tsx +145 -0
- package/src/components/command.story.tsx +121 -0
- package/src/components/context-menu.story.tsx +125 -0
- package/src/components/copy.story.tsx +77 -0
- package/src/components/dialog.story.tsx +137 -0
- package/src/components/drawer.story.tsx +131 -0
- package/src/components/dropdown-menu.story.tsx +208 -0
- package/src/components/empty.story.tsx +115 -0
- package/src/components/hover-card.story.tsx +102 -0
- package/src/components/image-with-fallback.story.tsx +105 -0
- package/src/components/input-group.story.tsx +119 -0
- package/src/components/input-otp.story.tsx +105 -0
- package/src/components/input.story.tsx +77 -0
- package/src/components/kbd.story.tsx +113 -0
- package/src/components/label.story.tsx +52 -0
- package/src/components/menubar.story.tsx +152 -0
- package/src/components/multi-select.story.tsx +122 -0
- package/src/components/navigation-menu.story.tsx +154 -0
- package/src/components/popover.story.tsx +127 -0
- package/src/components/preloader.story.tsx +86 -0
- package/src/components/progress.story.tsx +97 -0
- package/src/components/radio-group.story.tsx +113 -0
- package/src/components/resizable.story.tsx +119 -0
- package/src/components/responsive-sheet.story.tsx +117 -0
- package/src/components/scroll-area.story.tsx +112 -0
- package/src/components/select.story.tsx +112 -0
- package/src/components/separator.story.tsx +69 -0
- package/src/components/sheet.story.tsx +148 -0
- package/src/components/skeleton.story.tsx +101 -0
- package/src/components/slider.story.tsx +113 -0
- package/src/components/spinner.story.tsx +66 -0
- package/src/components/switch.story.tsx +98 -0
- package/src/components/table.story.tsx +148 -0
- package/src/components/tabs.story.tsx +98 -0
- package/src/components/tabs.tsx +1 -1
- package/src/components/textarea.story.tsx +94 -0
- package/src/components/toggle-group.story.tsx +118 -0
- package/src/components/toggle.story.tsx +104 -0
- package/src/components/tooltip.story.tsx +139 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { defineStory } from '@djangocfg/playground';
|
|
3
|
+
import {
|
|
4
|
+
Menubar,
|
|
5
|
+
MenubarMenu,
|
|
6
|
+
MenubarTrigger,
|
|
7
|
+
MenubarContent,
|
|
8
|
+
MenubarItem,
|
|
9
|
+
MenubarSeparator,
|
|
10
|
+
MenubarShortcut,
|
|
11
|
+
MenubarSub,
|
|
12
|
+
MenubarSubTrigger,
|
|
13
|
+
MenubarSubContent,
|
|
14
|
+
MenubarCheckboxItem,
|
|
15
|
+
MenubarRadioGroup,
|
|
16
|
+
MenubarRadioItem,
|
|
17
|
+
} from './menubar';
|
|
18
|
+
|
|
19
|
+
export default defineStory({
|
|
20
|
+
title: 'Core/Menubar',
|
|
21
|
+
component: Menubar,
|
|
22
|
+
description: 'Horizontal menu bar with dropdowns.',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const Default = () => (
|
|
26
|
+
<Menubar>
|
|
27
|
+
<MenubarMenu>
|
|
28
|
+
<MenubarTrigger>File</MenubarTrigger>
|
|
29
|
+
<MenubarContent>
|
|
30
|
+
<MenubarItem>
|
|
31
|
+
New Tab <MenubarShortcut>⌘T</MenubarShortcut>
|
|
32
|
+
</MenubarItem>
|
|
33
|
+
<MenubarItem>
|
|
34
|
+
New Window <MenubarShortcut>⌘N</MenubarShortcut>
|
|
35
|
+
</MenubarItem>
|
|
36
|
+
<MenubarSeparator />
|
|
37
|
+
<MenubarItem>Share</MenubarItem>
|
|
38
|
+
<MenubarSeparator />
|
|
39
|
+
<MenubarItem>
|
|
40
|
+
Print <MenubarShortcut>⌘P</MenubarShortcut>
|
|
41
|
+
</MenubarItem>
|
|
42
|
+
</MenubarContent>
|
|
43
|
+
</MenubarMenu>
|
|
44
|
+
<MenubarMenu>
|
|
45
|
+
<MenubarTrigger>Edit</MenubarTrigger>
|
|
46
|
+
<MenubarContent>
|
|
47
|
+
<MenubarItem>
|
|
48
|
+
Undo <MenubarShortcut>⌘Z</MenubarShortcut>
|
|
49
|
+
</MenubarItem>
|
|
50
|
+
<MenubarItem>
|
|
51
|
+
Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut>
|
|
52
|
+
</MenubarItem>
|
|
53
|
+
<MenubarSeparator />
|
|
54
|
+
<MenubarItem>
|
|
55
|
+
Cut <MenubarShortcut>⌘X</MenubarShortcut>
|
|
56
|
+
</MenubarItem>
|
|
57
|
+
<MenubarItem>
|
|
58
|
+
Copy <MenubarShortcut>⌘C</MenubarShortcut>
|
|
59
|
+
</MenubarItem>
|
|
60
|
+
<MenubarItem>
|
|
61
|
+
Paste <MenubarShortcut>⌘V</MenubarShortcut>
|
|
62
|
+
</MenubarItem>
|
|
63
|
+
</MenubarContent>
|
|
64
|
+
</MenubarMenu>
|
|
65
|
+
<MenubarMenu>
|
|
66
|
+
<MenubarTrigger>View</MenubarTrigger>
|
|
67
|
+
<MenubarContent>
|
|
68
|
+
<MenubarItem>Zoom In</MenubarItem>
|
|
69
|
+
<MenubarItem>Zoom Out</MenubarItem>
|
|
70
|
+
<MenubarSeparator />
|
|
71
|
+
<MenubarItem>
|
|
72
|
+
Toggle Fullscreen <MenubarShortcut>F11</MenubarShortcut>
|
|
73
|
+
</MenubarItem>
|
|
74
|
+
</MenubarContent>
|
|
75
|
+
</MenubarMenu>
|
|
76
|
+
</Menubar>
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
export const WithSubMenus = () => (
|
|
80
|
+
<Menubar>
|
|
81
|
+
<MenubarMenu>
|
|
82
|
+
<MenubarTrigger>File</MenubarTrigger>
|
|
83
|
+
<MenubarContent>
|
|
84
|
+
<MenubarItem>New File</MenubarItem>
|
|
85
|
+
<MenubarSub>
|
|
86
|
+
<MenubarSubTrigger>New</MenubarSubTrigger>
|
|
87
|
+
<MenubarSubContent>
|
|
88
|
+
<MenubarItem>Project...</MenubarItem>
|
|
89
|
+
<MenubarItem>Folder...</MenubarItem>
|
|
90
|
+
<MenubarItem>File...</MenubarItem>
|
|
91
|
+
</MenubarSubContent>
|
|
92
|
+
</MenubarSub>
|
|
93
|
+
<MenubarSeparator />
|
|
94
|
+
<MenubarItem>Open...</MenubarItem>
|
|
95
|
+
<MenubarSub>
|
|
96
|
+
<MenubarSubTrigger>Open Recent</MenubarSubTrigger>
|
|
97
|
+
<MenubarSubContent>
|
|
98
|
+
<MenubarItem>Project 1</MenubarItem>
|
|
99
|
+
<MenubarItem>Project 2</MenubarItem>
|
|
100
|
+
<MenubarItem>Project 3</MenubarItem>
|
|
101
|
+
</MenubarSubContent>
|
|
102
|
+
</MenubarSub>
|
|
103
|
+
</MenubarContent>
|
|
104
|
+
</MenubarMenu>
|
|
105
|
+
</Menubar>
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
export const WithCheckboxes = () => {
|
|
109
|
+
const [showStatusBar, setShowStatusBar] = useState(true);
|
|
110
|
+
const [showActivityBar, setShowActivityBar] = useState(false);
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<Menubar>
|
|
114
|
+
<MenubarMenu>
|
|
115
|
+
<MenubarTrigger>View</MenubarTrigger>
|
|
116
|
+
<MenubarContent>
|
|
117
|
+
<MenubarCheckboxItem
|
|
118
|
+
checked={showStatusBar}
|
|
119
|
+
onCheckedChange={setShowStatusBar}
|
|
120
|
+
>
|
|
121
|
+
Status Bar
|
|
122
|
+
</MenubarCheckboxItem>
|
|
123
|
+
<MenubarCheckboxItem
|
|
124
|
+
checked={showActivityBar}
|
|
125
|
+
onCheckedChange={setShowActivityBar}
|
|
126
|
+
>
|
|
127
|
+
Activity Bar
|
|
128
|
+
</MenubarCheckboxItem>
|
|
129
|
+
</MenubarContent>
|
|
130
|
+
</MenubarMenu>
|
|
131
|
+
</Menubar>
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const WithRadioGroup = () => {
|
|
136
|
+
const [theme, setTheme] = useState('system');
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<Menubar>
|
|
140
|
+
<MenubarMenu>
|
|
141
|
+
<MenubarTrigger>Preferences</MenubarTrigger>
|
|
142
|
+
<MenubarContent>
|
|
143
|
+
<MenubarRadioGroup value={theme} onValueChange={setTheme}>
|
|
144
|
+
<MenubarRadioItem value="light">Light</MenubarRadioItem>
|
|
145
|
+
<MenubarRadioItem value="dark">Dark</MenubarRadioItem>
|
|
146
|
+
<MenubarRadioItem value="system">System</MenubarRadioItem>
|
|
147
|
+
</MenubarRadioGroup>
|
|
148
|
+
</MenubarContent>
|
|
149
|
+
</MenubarMenu>
|
|
150
|
+
</Menubar>
|
|
151
|
+
);
|
|
152
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { defineStory } from '@djangocfg/playground';
|
|
3
|
+
import { MultiSelect, type MultiSelectOption } from './multi-select';
|
|
4
|
+
import { Label } from './label';
|
|
5
|
+
|
|
6
|
+
export default defineStory({
|
|
7
|
+
title: 'Core/MultiSelect',
|
|
8
|
+
component: MultiSelect,
|
|
9
|
+
description: 'Multi-select dropdown with badges.',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const frameworks: MultiSelectOption[] = [
|
|
13
|
+
{ value: 'react', label: 'React' },
|
|
14
|
+
{ value: 'vue', label: 'Vue' },
|
|
15
|
+
{ value: 'angular', label: 'Angular' },
|
|
16
|
+
{ value: 'svelte', label: 'Svelte' },
|
|
17
|
+
{ value: 'solid', label: 'Solid' },
|
|
18
|
+
{ value: 'preact', label: 'Preact' },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const languages: MultiSelectOption[] = [
|
|
22
|
+
{ value: 'typescript', label: 'TypeScript', description: 'Typed JavaScript' },
|
|
23
|
+
{ value: 'javascript', label: 'JavaScript', description: 'Dynamic scripting' },
|
|
24
|
+
{ value: 'python', label: 'Python', description: 'General purpose' },
|
|
25
|
+
{ value: 'rust', label: 'Rust', description: 'Systems programming' },
|
|
26
|
+
{ value: 'go', label: 'Go', description: 'Backend services' },
|
|
27
|
+
{ value: 'java', label: 'Java', description: 'Enterprise apps' },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
export const Default = () => {
|
|
31
|
+
const [value, setValue] = useState<string[]>([]);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div className="max-w-sm">
|
|
35
|
+
<MultiSelect
|
|
36
|
+
options={frameworks}
|
|
37
|
+
value={value}
|
|
38
|
+
onChange={setValue}
|
|
39
|
+
placeholder="Select frameworks..."
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const WithLabel = () => {
|
|
46
|
+
const [value, setValue] = useState<string[]>([]);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div className="max-w-sm space-y-2">
|
|
50
|
+
<Label>Frameworks</Label>
|
|
51
|
+
<MultiSelect
|
|
52
|
+
options={frameworks}
|
|
53
|
+
value={value}
|
|
54
|
+
onChange={setValue}
|
|
55
|
+
placeholder="Select frameworks..."
|
|
56
|
+
searchPlaceholder="Search frameworks..."
|
|
57
|
+
emptyText="No frameworks found."
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const WithDescriptions = () => {
|
|
64
|
+
const [value, setValue] = useState<string[]>([]);
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div className="max-w-sm space-y-2">
|
|
68
|
+
<Label>Languages</Label>
|
|
69
|
+
<MultiSelect
|
|
70
|
+
options={languages}
|
|
71
|
+
value={value}
|
|
72
|
+
onChange={setValue}
|
|
73
|
+
placeholder="Select languages..."
|
|
74
|
+
/>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const WithDefaultValue = () => {
|
|
80
|
+
const [value, setValue] = useState<string[]>(['react', 'vue']);
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div className="max-w-sm space-y-2">
|
|
84
|
+
<Label>Selected Frameworks</Label>
|
|
85
|
+
<MultiSelect
|
|
86
|
+
options={frameworks}
|
|
87
|
+
value={value}
|
|
88
|
+
onChange={setValue}
|
|
89
|
+
placeholder="Select frameworks..."
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const MaxDisplay = () => {
|
|
96
|
+
const [value, setValue] = useState<string[]>(['react', 'vue', 'angular', 'svelte']);
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<div className="max-w-sm space-y-2">
|
|
100
|
+
<Label>Frameworks (max 2 displayed)</Label>
|
|
101
|
+
<MultiSelect
|
|
102
|
+
options={frameworks}
|
|
103
|
+
value={value}
|
|
104
|
+
onChange={setValue}
|
|
105
|
+
placeholder="Select frameworks..."
|
|
106
|
+
maxDisplay={2}
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const Disabled = () => (
|
|
113
|
+
<div className="max-w-sm">
|
|
114
|
+
<MultiSelect
|
|
115
|
+
options={frameworks}
|
|
116
|
+
value={['react']}
|
|
117
|
+
onChange={() => {}}
|
|
118
|
+
placeholder="Select frameworks..."
|
|
119
|
+
disabled
|
|
120
|
+
/>
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { defineStory } from '@djangocfg/playground';
|
|
2
|
+
import {
|
|
3
|
+
NavigationMenu,
|
|
4
|
+
NavigationMenuList,
|
|
5
|
+
NavigationMenuItem,
|
|
6
|
+
NavigationMenuTrigger,
|
|
7
|
+
NavigationMenuContent,
|
|
8
|
+
NavigationMenuLink,
|
|
9
|
+
navigationMenuTriggerStyle,
|
|
10
|
+
} from './navigation-menu';
|
|
11
|
+
import { cn } from '../lib';
|
|
12
|
+
|
|
13
|
+
export default defineStory({
|
|
14
|
+
title: 'Core/NavigationMenu',
|
|
15
|
+
component: NavigationMenu,
|
|
16
|
+
description: 'Navigation menu with dropdowns and links.',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const ListItem = ({
|
|
20
|
+
className,
|
|
21
|
+
title,
|
|
22
|
+
children,
|
|
23
|
+
href,
|
|
24
|
+
}: {
|
|
25
|
+
className?: string;
|
|
26
|
+
title: string;
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
href: string;
|
|
29
|
+
}) => (
|
|
30
|
+
<li>
|
|
31
|
+
<NavigationMenuLink asChild>
|
|
32
|
+
<a
|
|
33
|
+
className={cn(
|
|
34
|
+
'block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground',
|
|
35
|
+
className
|
|
36
|
+
)}
|
|
37
|
+
href={href}
|
|
38
|
+
>
|
|
39
|
+
<div className="text-sm font-medium leading-none">{title}</div>
|
|
40
|
+
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
|
41
|
+
{children}
|
|
42
|
+
</p>
|
|
43
|
+
</a>
|
|
44
|
+
</NavigationMenuLink>
|
|
45
|
+
</li>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
export const Default = () => (
|
|
49
|
+
<NavigationMenu>
|
|
50
|
+
<NavigationMenuList>
|
|
51
|
+
<NavigationMenuItem>
|
|
52
|
+
<NavigationMenuTrigger>Getting Started</NavigationMenuTrigger>
|
|
53
|
+
<NavigationMenuContent>
|
|
54
|
+
<ul className="grid gap-3 p-4 w-[400px]">
|
|
55
|
+
<ListItem href="#" title="Introduction">
|
|
56
|
+
Re-usable components built with Radix UI and Tailwind CSS.
|
|
57
|
+
</ListItem>
|
|
58
|
+
<ListItem href="#" title="Installation">
|
|
59
|
+
How to install dependencies and structure your app.
|
|
60
|
+
</ListItem>
|
|
61
|
+
<ListItem href="#" title="Typography">
|
|
62
|
+
Styles for headings, paragraphs, lists, and more.
|
|
63
|
+
</ListItem>
|
|
64
|
+
</ul>
|
|
65
|
+
</NavigationMenuContent>
|
|
66
|
+
</NavigationMenuItem>
|
|
67
|
+
<NavigationMenuItem>
|
|
68
|
+
<NavigationMenuTrigger>Components</NavigationMenuTrigger>
|
|
69
|
+
<NavigationMenuContent>
|
|
70
|
+
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2">
|
|
71
|
+
<ListItem href="#" title="Alert Dialog">
|
|
72
|
+
A modal dialog that interrupts the user.
|
|
73
|
+
</ListItem>
|
|
74
|
+
<ListItem href="#" title="Hover Card">
|
|
75
|
+
For sighted users to preview content.
|
|
76
|
+
</ListItem>
|
|
77
|
+
<ListItem href="#" title="Progress">
|
|
78
|
+
Displays an indicator showing completion progress.
|
|
79
|
+
</ListItem>
|
|
80
|
+
<ListItem href="#" title="Scroll Area">
|
|
81
|
+
Visually or semantically separates content.
|
|
82
|
+
</ListItem>
|
|
83
|
+
</ul>
|
|
84
|
+
</NavigationMenuContent>
|
|
85
|
+
</NavigationMenuItem>
|
|
86
|
+
<NavigationMenuItem>
|
|
87
|
+
<NavigationMenuLink className={navigationMenuTriggerStyle()} href="#">
|
|
88
|
+
Documentation
|
|
89
|
+
</NavigationMenuLink>
|
|
90
|
+
</NavigationMenuItem>
|
|
91
|
+
</NavigationMenuList>
|
|
92
|
+
</NavigationMenu>
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
export const Simple = () => (
|
|
96
|
+
<NavigationMenu>
|
|
97
|
+
<NavigationMenuList>
|
|
98
|
+
<NavigationMenuItem>
|
|
99
|
+
<NavigationMenuLink className={navigationMenuTriggerStyle()} href="#">
|
|
100
|
+
Home
|
|
101
|
+
</NavigationMenuLink>
|
|
102
|
+
</NavigationMenuItem>
|
|
103
|
+
<NavigationMenuItem>
|
|
104
|
+
<NavigationMenuLink className={navigationMenuTriggerStyle()} href="#">
|
|
105
|
+
About
|
|
106
|
+
</NavigationMenuLink>
|
|
107
|
+
</NavigationMenuItem>
|
|
108
|
+
<NavigationMenuItem>
|
|
109
|
+
<NavigationMenuLink className={navigationMenuTriggerStyle()} href="#">
|
|
110
|
+
Contact
|
|
111
|
+
</NavigationMenuLink>
|
|
112
|
+
</NavigationMenuItem>
|
|
113
|
+
</NavigationMenuList>
|
|
114
|
+
</NavigationMenu>
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
export const WithFeatureCard = () => (
|
|
118
|
+
<NavigationMenu>
|
|
119
|
+
<NavigationMenuList>
|
|
120
|
+
<NavigationMenuItem>
|
|
121
|
+
<NavigationMenuTrigger>Products</NavigationMenuTrigger>
|
|
122
|
+
<NavigationMenuContent>
|
|
123
|
+
<ul className="grid gap-3 p-6 w-[400px] md:w-[500px] lg:grid-cols-[.75fr_1fr]">
|
|
124
|
+
<li className="row-span-3">
|
|
125
|
+
<NavigationMenuLink asChild>
|
|
126
|
+
<a
|
|
127
|
+
className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md"
|
|
128
|
+
href="#"
|
|
129
|
+
>
|
|
130
|
+
<div className="mb-2 mt-4 text-lg font-medium">
|
|
131
|
+
Featured Product
|
|
132
|
+
</div>
|
|
133
|
+
<p className="text-sm leading-tight text-muted-foreground">
|
|
134
|
+
Beautifully designed components built with Radix UI and
|
|
135
|
+
Tailwind CSS.
|
|
136
|
+
</p>
|
|
137
|
+
</a>
|
|
138
|
+
</NavigationMenuLink>
|
|
139
|
+
</li>
|
|
140
|
+
<ListItem href="#" title="Product A">
|
|
141
|
+
A high-performance solution for modern needs.
|
|
142
|
+
</ListItem>
|
|
143
|
+
<ListItem href="#" title="Product B">
|
|
144
|
+
Enterprise-grade security and reliability.
|
|
145
|
+
</ListItem>
|
|
146
|
+
<ListItem href="#" title="Product C">
|
|
147
|
+
Scalable infrastructure for growing teams.
|
|
148
|
+
</ListItem>
|
|
149
|
+
</ul>
|
|
150
|
+
</NavigationMenuContent>
|
|
151
|
+
</NavigationMenuItem>
|
|
152
|
+
</NavigationMenuList>
|
|
153
|
+
</NavigationMenu>
|
|
154
|
+
);
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { defineStory, useSelect } from '@djangocfg/playground';
|
|
2
|
+
import { Popover, PopoverContent, PopoverTrigger } from './popover';
|
|
3
|
+
import { Button } from './button';
|
|
4
|
+
import { Input } from './input';
|
|
5
|
+
import { Label } from './label';
|
|
6
|
+
|
|
7
|
+
export default defineStory({
|
|
8
|
+
title: 'Core/Popover',
|
|
9
|
+
component: Popover,
|
|
10
|
+
description: 'Floating content panel triggered by a button.',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const Interactive = () => {
|
|
14
|
+
const [side] = useSelect('side', {
|
|
15
|
+
options: ['top', 'right', 'bottom', 'left'] as const,
|
|
16
|
+
defaultValue: 'bottom',
|
|
17
|
+
label: 'Side',
|
|
18
|
+
description: 'Popover position',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const [align] = useSelect('align', {
|
|
22
|
+
options: ['start', 'center', 'end'] as const,
|
|
23
|
+
defaultValue: 'center',
|
|
24
|
+
label: 'Align',
|
|
25
|
+
description: 'Popover alignment',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className="flex justify-center p-20">
|
|
30
|
+
<Popover>
|
|
31
|
+
<PopoverTrigger asChild>
|
|
32
|
+
<Button variant="outline">Open popover</Button>
|
|
33
|
+
</PopoverTrigger>
|
|
34
|
+
<PopoverContent side={side} align={align} className="w-80">
|
|
35
|
+
<div className="grid gap-4">
|
|
36
|
+
<div className="space-y-2">
|
|
37
|
+
<h4 className="font-medium leading-none">Dimensions</h4>
|
|
38
|
+
<p className="text-sm text-muted-foreground">
|
|
39
|
+
Set the dimensions for the layer.
|
|
40
|
+
</p>
|
|
41
|
+
</div>
|
|
42
|
+
<div className="grid gap-2">
|
|
43
|
+
<div className="grid grid-cols-3 items-center gap-4">
|
|
44
|
+
<Label htmlFor="width">Width</Label>
|
|
45
|
+
<Input id="width" defaultValue="100%" className="col-span-2 h-8" />
|
|
46
|
+
</div>
|
|
47
|
+
<div className="grid grid-cols-3 items-center gap-4">
|
|
48
|
+
<Label htmlFor="height">Height</Label>
|
|
49
|
+
<Input id="height" defaultValue="25px" className="col-span-2 h-8" />
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</PopoverContent>
|
|
54
|
+
</Popover>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const Default = () => (
|
|
60
|
+
<Popover>
|
|
61
|
+
<PopoverTrigger asChild>
|
|
62
|
+
<Button variant="outline">Open popover</Button>
|
|
63
|
+
</PopoverTrigger>
|
|
64
|
+
<PopoverContent className="w-80">
|
|
65
|
+
<div className="grid gap-4">
|
|
66
|
+
<div className="space-y-2">
|
|
67
|
+
<h4 className="font-medium leading-none">Dimensions</h4>
|
|
68
|
+
<p className="text-sm text-muted-foreground">
|
|
69
|
+
Set the dimensions for the layer.
|
|
70
|
+
</p>
|
|
71
|
+
</div>
|
|
72
|
+
<div className="grid gap-2">
|
|
73
|
+
<div className="grid grid-cols-3 items-center gap-4">
|
|
74
|
+
<Label htmlFor="width">Width</Label>
|
|
75
|
+
<Input id="width" defaultValue="100%" className="col-span-2 h-8" />
|
|
76
|
+
</div>
|
|
77
|
+
<div className="grid grid-cols-3 items-center gap-4">
|
|
78
|
+
<Label htmlFor="maxWidth">Max. width</Label>
|
|
79
|
+
<Input id="maxWidth" defaultValue="300px" className="col-span-2 h-8" />
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</PopoverContent>
|
|
84
|
+
</Popover>
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
export const WithForm = () => (
|
|
88
|
+
<Popover>
|
|
89
|
+
<PopoverTrigger asChild>
|
|
90
|
+
<Button>Update settings</Button>
|
|
91
|
+
</PopoverTrigger>
|
|
92
|
+
<PopoverContent className="w-80">
|
|
93
|
+
<div className="grid gap-4">
|
|
94
|
+
<div className="space-y-2">
|
|
95
|
+
<h4 className="font-medium leading-none">Settings</h4>
|
|
96
|
+
<p className="text-sm text-muted-foreground">
|
|
97
|
+
Configure your preferences.
|
|
98
|
+
</p>
|
|
99
|
+
</div>
|
|
100
|
+
<div className="space-y-4">
|
|
101
|
+
<div className="space-y-2">
|
|
102
|
+
<Label htmlFor="name">Display Name</Label>
|
|
103
|
+
<Input id="name" placeholder="Enter name" />
|
|
104
|
+
</div>
|
|
105
|
+
<div className="space-y-2">
|
|
106
|
+
<Label htmlFor="email">Email</Label>
|
|
107
|
+
<Input id="email" type="email" placeholder="Enter email" />
|
|
108
|
+
</div>
|
|
109
|
+
<Button className="w-full">Save</Button>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</PopoverContent>
|
|
113
|
+
</Popover>
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
export const Simple = () => (
|
|
117
|
+
<Popover>
|
|
118
|
+
<PopoverTrigger asChild>
|
|
119
|
+
<Button variant="outline" size="sm">Info</Button>
|
|
120
|
+
</PopoverTrigger>
|
|
121
|
+
<PopoverContent className="w-64">
|
|
122
|
+
<p className="text-sm">
|
|
123
|
+
This is a simple popover with just some text content.
|
|
124
|
+
</p>
|
|
125
|
+
</PopoverContent>
|
|
126
|
+
</Popover>
|
|
127
|
+
);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { defineStory, useSelect, useBoolean } from '@djangocfg/playground';
|
|
2
|
+
import { Preloader, PreloaderSkeleton } from './preloader';
|
|
3
|
+
|
|
4
|
+
export default defineStory({
|
|
5
|
+
title: 'Core/Preloader',
|
|
6
|
+
component: Preloader,
|
|
7
|
+
description: 'Loading indicators with multiple variants.',
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const Interactive = () => {
|
|
11
|
+
const [size] = useSelect('size', {
|
|
12
|
+
options: ['sm', 'md', 'lg', 'xl'] as const,
|
|
13
|
+
defaultValue: 'md',
|
|
14
|
+
label: 'Size',
|
|
15
|
+
description: 'Spinner size',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const [showText] = useBoolean('showText', {
|
|
19
|
+
defaultValue: true,
|
|
20
|
+
label: 'Show Text',
|
|
21
|
+
description: 'Display loading text',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Preloader
|
|
26
|
+
size={size}
|
|
27
|
+
text={showText ? 'Loading...' : undefined}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Default = () => <Preloader />;
|
|
33
|
+
|
|
34
|
+
export const WithText = () => <Preloader text="Loading data..." />;
|
|
35
|
+
|
|
36
|
+
export const WithDescription = () => (
|
|
37
|
+
<Preloader
|
|
38
|
+
text="Processing"
|
|
39
|
+
description="Please wait while we process your request"
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
export const Sizes = () => (
|
|
44
|
+
<div className="flex items-center gap-8">
|
|
45
|
+
<div className="flex flex-col items-center gap-2">
|
|
46
|
+
<Preloader size="sm" />
|
|
47
|
+
<span className="text-xs text-muted-foreground">sm</span>
|
|
48
|
+
</div>
|
|
49
|
+
<div className="flex flex-col items-center gap-2">
|
|
50
|
+
<Preloader size="md" />
|
|
51
|
+
<span className="text-xs text-muted-foreground">md</span>
|
|
52
|
+
</div>
|
|
53
|
+
<div className="flex flex-col items-center gap-2">
|
|
54
|
+
<Preloader size="lg" />
|
|
55
|
+
<span className="text-xs text-muted-foreground">lg</span>
|
|
56
|
+
</div>
|
|
57
|
+
<div className="flex flex-col items-center gap-2">
|
|
58
|
+
<Preloader size="xl" />
|
|
59
|
+
<span className="text-xs text-muted-foreground">xl</span>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
export const InCard = () => (
|
|
65
|
+
<div className="rounded-lg border p-8">
|
|
66
|
+
<Preloader text="Loading content..." size="lg" />
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
export const SkeletonDefault = () => <PreloaderSkeleton />;
|
|
71
|
+
|
|
72
|
+
export const SkeletonWithAvatar = () => <PreloaderSkeleton showAvatar />;
|
|
73
|
+
|
|
74
|
+
export const SkeletonLines = () => (
|
|
75
|
+
<div className="max-w-md space-y-6">
|
|
76
|
+
<PreloaderSkeleton lines={2} />
|
|
77
|
+
<PreloaderSkeleton lines={4} />
|
|
78
|
+
<PreloaderSkeleton lines={1} />
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
export const SkeletonCard = () => (
|
|
83
|
+
<div className="max-w-sm rounded-lg border p-4">
|
|
84
|
+
<PreloaderSkeleton showAvatar lines={2} />
|
|
85
|
+
</div>
|
|
86
|
+
);
|