@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.
Files changed (54) hide show
  1. package/package.json +8 -5
  2. package/src/components/accordion.story.tsx +110 -0
  3. package/src/components/alert-dialog.story.tsx +104 -0
  4. package/src/components/alert.story.tsx +77 -0
  5. package/src/components/aspect-ratio.story.tsx +94 -0
  6. package/src/components/avatar.story.tsx +115 -0
  7. package/src/components/badge.story.tsx +56 -0
  8. package/src/components/button-download.story.tsx +112 -0
  9. package/src/components/button-group.story.tsx +79 -0
  10. package/src/components/button.story.tsx +116 -0
  11. package/src/components/calendar.story.tsx +126 -0
  12. package/src/components/card.story.tsx +105 -0
  13. package/src/components/carousel.story.tsx +122 -0
  14. package/src/components/checkbox.story.tsx +89 -0
  15. package/src/components/collapsible.story.tsx +133 -0
  16. package/src/components/combobox.story.tsx +145 -0
  17. package/src/components/command.story.tsx +121 -0
  18. package/src/components/context-menu.story.tsx +125 -0
  19. package/src/components/copy.story.tsx +77 -0
  20. package/src/components/dialog.story.tsx +137 -0
  21. package/src/components/drawer.story.tsx +131 -0
  22. package/src/components/dropdown-menu.story.tsx +208 -0
  23. package/src/components/empty.story.tsx +115 -0
  24. package/src/components/hover-card.story.tsx +102 -0
  25. package/src/components/image-with-fallback.story.tsx +105 -0
  26. package/src/components/input-group.story.tsx +119 -0
  27. package/src/components/input-otp.story.tsx +105 -0
  28. package/src/components/input.story.tsx +77 -0
  29. package/src/components/kbd.story.tsx +113 -0
  30. package/src/components/label.story.tsx +52 -0
  31. package/src/components/menubar.story.tsx +152 -0
  32. package/src/components/multi-select.story.tsx +122 -0
  33. package/src/components/navigation-menu.story.tsx +154 -0
  34. package/src/components/popover.story.tsx +127 -0
  35. package/src/components/preloader.story.tsx +86 -0
  36. package/src/components/progress.story.tsx +97 -0
  37. package/src/components/radio-group.story.tsx +113 -0
  38. package/src/components/resizable.story.tsx +119 -0
  39. package/src/components/responsive-sheet.story.tsx +117 -0
  40. package/src/components/scroll-area.story.tsx +112 -0
  41. package/src/components/select.story.tsx +112 -0
  42. package/src/components/separator.story.tsx +69 -0
  43. package/src/components/sheet.story.tsx +148 -0
  44. package/src/components/skeleton.story.tsx +101 -0
  45. package/src/components/slider.story.tsx +113 -0
  46. package/src/components/spinner.story.tsx +66 -0
  47. package/src/components/switch.story.tsx +98 -0
  48. package/src/components/table.story.tsx +148 -0
  49. package/src/components/tabs.story.tsx +98 -0
  50. package/src/components/tabs.tsx +1 -1
  51. package/src/components/textarea.story.tsx +94 -0
  52. package/src/components/toggle-group.story.tsx +118 -0
  53. package/src/components/toggle.story.tsx +104 -0
  54. 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
+ );