@djangocfg/ui-core 2.1.120 → 2.1.123
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/carousel.tsx +2 -2
- 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,69 @@
|
|
|
1
|
+
import { defineStory } from '@djangocfg/playground';
|
|
2
|
+
import { Separator } from './separator';
|
|
3
|
+
|
|
4
|
+
export default defineStory({
|
|
5
|
+
title: 'Core/Separator',
|
|
6
|
+
component: Separator,
|
|
7
|
+
description: 'Visual divider between content sections.',
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const Default = () => (
|
|
11
|
+
<div>
|
|
12
|
+
<div className="space-y-1">
|
|
13
|
+
<h4 className="text-sm font-medium leading-none">Radix Primitives</h4>
|
|
14
|
+
<p className="text-sm text-muted-foreground">
|
|
15
|
+
An open-source UI component library.
|
|
16
|
+
</p>
|
|
17
|
+
</div>
|
|
18
|
+
<Separator className="my-4" />
|
|
19
|
+
<div className="flex h-5 items-center space-x-4 text-sm">
|
|
20
|
+
<div>Blog</div>
|
|
21
|
+
<Separator orientation="vertical" />
|
|
22
|
+
<div>Docs</div>
|
|
23
|
+
<Separator orientation="vertical" />
|
|
24
|
+
<div>Source</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export const Horizontal = () => (
|
|
30
|
+
<div className="max-w-md">
|
|
31
|
+
<p className="text-sm text-muted-foreground">First section</p>
|
|
32
|
+
<Separator className="my-4" />
|
|
33
|
+
<p className="text-sm text-muted-foreground">Second section</p>
|
|
34
|
+
<Separator className="my-4" />
|
|
35
|
+
<p className="text-sm text-muted-foreground">Third section</p>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export const Vertical = () => (
|
|
40
|
+
<div className="flex h-5 items-center space-x-4 text-sm">
|
|
41
|
+
<div>Home</div>
|
|
42
|
+
<Separator orientation="vertical" />
|
|
43
|
+
<div>About</div>
|
|
44
|
+
<Separator orientation="vertical" />
|
|
45
|
+
<div>Products</div>
|
|
46
|
+
<Separator orientation="vertical" />
|
|
47
|
+
<div>Contact</div>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
export const InCard = () => (
|
|
52
|
+
<div className="rounded-lg border p-4 max-w-sm">
|
|
53
|
+
<h4 className="font-medium">Card Title</h4>
|
|
54
|
+
<Separator className="my-3" />
|
|
55
|
+
<p className="text-sm text-muted-foreground">
|
|
56
|
+
This is some card content below the separator.
|
|
57
|
+
</p>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
export const WithLabels = () => (
|
|
62
|
+
<div className="max-w-md">
|
|
63
|
+
<div className="flex items-center gap-4">
|
|
64
|
+
<Separator className="flex-1" />
|
|
65
|
+
<span className="text-sm text-muted-foreground">OR</span>
|
|
66
|
+
<Separator className="flex-1" />
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { defineStory, useSelect } from '@djangocfg/playground';
|
|
2
|
+
import {
|
|
3
|
+
Sheet,
|
|
4
|
+
SheetTrigger,
|
|
5
|
+
SheetContent,
|
|
6
|
+
SheetHeader,
|
|
7
|
+
SheetFooter,
|
|
8
|
+
SheetTitle,
|
|
9
|
+
SheetDescription,
|
|
10
|
+
SheetClose,
|
|
11
|
+
} from './sheet';
|
|
12
|
+
import { Button } from './button';
|
|
13
|
+
import { Input } from './input';
|
|
14
|
+
import { Label } from './label';
|
|
15
|
+
|
|
16
|
+
export default defineStory({
|
|
17
|
+
title: 'Core/Sheet',
|
|
18
|
+
component: Sheet,
|
|
19
|
+
description: 'Slide-out panel from the edge of the screen.',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const Interactive = () => {
|
|
23
|
+
const [side] = useSelect('side', {
|
|
24
|
+
options: ['top', 'right', 'bottom', 'left'] as const,
|
|
25
|
+
defaultValue: 'right',
|
|
26
|
+
label: 'Side',
|
|
27
|
+
description: 'Sheet position',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Sheet>
|
|
32
|
+
<SheetTrigger asChild>
|
|
33
|
+
<Button variant="outline">Open Sheet</Button>
|
|
34
|
+
</SheetTrigger>
|
|
35
|
+
<SheetContent side={side}>
|
|
36
|
+
<SheetHeader>
|
|
37
|
+
<SheetTitle>Sheet Title</SheetTitle>
|
|
38
|
+
<SheetDescription>
|
|
39
|
+
This is a sheet that slides in from the {side}.
|
|
40
|
+
</SheetDescription>
|
|
41
|
+
</SheetHeader>
|
|
42
|
+
<div className="py-4">
|
|
43
|
+
<p>Sheet content goes here.</p>
|
|
44
|
+
</div>
|
|
45
|
+
<SheetFooter>
|
|
46
|
+
<SheetClose asChild>
|
|
47
|
+
<Button variant="outline">Cancel</Button>
|
|
48
|
+
</SheetClose>
|
|
49
|
+
<Button>Save</Button>
|
|
50
|
+
</SheetFooter>
|
|
51
|
+
</SheetContent>
|
|
52
|
+
</Sheet>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const Right = () => (
|
|
57
|
+
<Sheet>
|
|
58
|
+
<SheetTrigger asChild>
|
|
59
|
+
<Button variant="outline">Open Right</Button>
|
|
60
|
+
</SheetTrigger>
|
|
61
|
+
<SheetContent side="right">
|
|
62
|
+
<SheetHeader>
|
|
63
|
+
<SheetTitle>Edit Profile</SheetTitle>
|
|
64
|
+
<SheetDescription>
|
|
65
|
+
Make changes to your profile here.
|
|
66
|
+
</SheetDescription>
|
|
67
|
+
</SheetHeader>
|
|
68
|
+
<div className="space-y-4 py-4">
|
|
69
|
+
<div className="space-y-2">
|
|
70
|
+
<Label htmlFor="name">Name</Label>
|
|
71
|
+
<Input id="name" defaultValue="John Doe" />
|
|
72
|
+
</div>
|
|
73
|
+
<div className="space-y-2">
|
|
74
|
+
<Label htmlFor="email">Email</Label>
|
|
75
|
+
<Input id="email" defaultValue="john@example.com" />
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
<SheetFooter>
|
|
79
|
+
<SheetClose asChild>
|
|
80
|
+
<Button variant="outline">Cancel</Button>
|
|
81
|
+
</SheetClose>
|
|
82
|
+
<Button>Save changes</Button>
|
|
83
|
+
</SheetFooter>
|
|
84
|
+
</SheetContent>
|
|
85
|
+
</Sheet>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
export const Left = () => (
|
|
89
|
+
<Sheet>
|
|
90
|
+
<SheetTrigger asChild>
|
|
91
|
+
<Button variant="outline">Open Left</Button>
|
|
92
|
+
</SheetTrigger>
|
|
93
|
+
<SheetContent side="left">
|
|
94
|
+
<SheetHeader>
|
|
95
|
+
<SheetTitle>Navigation</SheetTitle>
|
|
96
|
+
</SheetHeader>
|
|
97
|
+
<nav className="flex flex-col gap-2 py-4">
|
|
98
|
+
<Button variant="ghost" className="justify-start">Dashboard</Button>
|
|
99
|
+
<Button variant="ghost" className="justify-start">Projects</Button>
|
|
100
|
+
<Button variant="ghost" className="justify-start">Settings</Button>
|
|
101
|
+
<Button variant="ghost" className="justify-start">Help</Button>
|
|
102
|
+
</nav>
|
|
103
|
+
</SheetContent>
|
|
104
|
+
</Sheet>
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
export const Bottom = () => (
|
|
108
|
+
<Sheet>
|
|
109
|
+
<SheetTrigger asChild>
|
|
110
|
+
<Button variant="outline">Open Bottom</Button>
|
|
111
|
+
</SheetTrigger>
|
|
112
|
+
<SheetContent side="bottom">
|
|
113
|
+
<SheetHeader>
|
|
114
|
+
<SheetTitle>Quick Actions</SheetTitle>
|
|
115
|
+
<SheetDescription>
|
|
116
|
+
Choose an action to perform.
|
|
117
|
+
</SheetDescription>
|
|
118
|
+
</SheetHeader>
|
|
119
|
+
<div className="flex gap-2 py-4">
|
|
120
|
+
<Button className="flex-1">Share</Button>
|
|
121
|
+
<Button className="flex-1" variant="outline">Copy Link</Button>
|
|
122
|
+
<Button className="flex-1" variant="destructive">Delete</Button>
|
|
123
|
+
</div>
|
|
124
|
+
</SheetContent>
|
|
125
|
+
</Sheet>
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
export const Top = () => (
|
|
129
|
+
<Sheet>
|
|
130
|
+
<SheetTrigger asChild>
|
|
131
|
+
<Button variant="outline">Open Top</Button>
|
|
132
|
+
</SheetTrigger>
|
|
133
|
+
<SheetContent side="top">
|
|
134
|
+
<SheetHeader>
|
|
135
|
+
<SheetTitle>Notification</SheetTitle>
|
|
136
|
+
<SheetDescription>
|
|
137
|
+
You have new updates available.
|
|
138
|
+
</SheetDescription>
|
|
139
|
+
</SheetHeader>
|
|
140
|
+
<div className="flex gap-2 py-4">
|
|
141
|
+
<Button>Update Now</Button>
|
|
142
|
+
<SheetClose asChild>
|
|
143
|
+
<Button variant="outline">Later</Button>
|
|
144
|
+
</SheetClose>
|
|
145
|
+
</div>
|
|
146
|
+
</SheetContent>
|
|
147
|
+
</Sheet>
|
|
148
|
+
);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { defineStory } from '@djangocfg/playground';
|
|
2
|
+
import { Skeleton } from './skeleton';
|
|
3
|
+
|
|
4
|
+
export default defineStory({
|
|
5
|
+
title: 'Core/Skeleton',
|
|
6
|
+
component: Skeleton,
|
|
7
|
+
description: 'Loading placeholder for content.',
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const Default = () => (
|
|
11
|
+
<div className="flex items-center space-x-4">
|
|
12
|
+
<Skeleton className="h-12 w-12 rounded-full" />
|
|
13
|
+
<div className="space-y-2">
|
|
14
|
+
<Skeleton className="h-4 w-[250px]" />
|
|
15
|
+
<Skeleton className="h-4 w-[200px]" />
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const Card = () => (
|
|
21
|
+
<div className="flex flex-col space-y-3">
|
|
22
|
+
<Skeleton className="h-[125px] w-[250px] rounded-xl" />
|
|
23
|
+
<div className="space-y-2">
|
|
24
|
+
<Skeleton className="h-4 w-[250px]" />
|
|
25
|
+
<Skeleton className="h-4 w-[200px]" />
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export const Table = () => (
|
|
31
|
+
<div className="space-y-2">
|
|
32
|
+
<div className="flex gap-4">
|
|
33
|
+
<Skeleton className="h-8 w-[100px]" />
|
|
34
|
+
<Skeleton className="h-8 w-[150px]" />
|
|
35
|
+
<Skeleton className="h-8 w-[100px]" />
|
|
36
|
+
<Skeleton className="h-8 w-[80px]" />
|
|
37
|
+
</div>
|
|
38
|
+
{[...Array(5)].map((_, i) => (
|
|
39
|
+
<div key={i} className="flex gap-4">
|
|
40
|
+
<Skeleton className="h-6 w-[100px]" />
|
|
41
|
+
<Skeleton className="h-6 w-[150px]" />
|
|
42
|
+
<Skeleton className="h-6 w-[100px]" />
|
|
43
|
+
<Skeleton className="h-6 w-[80px]" />
|
|
44
|
+
</div>
|
|
45
|
+
))}
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const Profile = () => (
|
|
50
|
+
<div className="flex items-start space-x-4">
|
|
51
|
+
<Skeleton className="h-16 w-16 rounded-full" />
|
|
52
|
+
<div className="space-y-2">
|
|
53
|
+
<Skeleton className="h-5 w-[180px]" />
|
|
54
|
+
<Skeleton className="h-4 w-[120px]" />
|
|
55
|
+
<Skeleton className="h-4 w-[220px]" />
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
export const Article = () => (
|
|
61
|
+
<div className="space-y-4 max-w-lg">
|
|
62
|
+
<Skeleton className="h-8 w-3/4" />
|
|
63
|
+
<Skeleton className="h-4 w-1/4" />
|
|
64
|
+
<Skeleton className="h-[200px] w-full rounded-lg" />
|
|
65
|
+
<div className="space-y-2">
|
|
66
|
+
<Skeleton className="h-4 w-full" />
|
|
67
|
+
<Skeleton className="h-4 w-full" />
|
|
68
|
+
<Skeleton className="h-4 w-3/4" />
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
export const Grid = () => (
|
|
74
|
+
<div className="grid grid-cols-3 gap-4">
|
|
75
|
+
{[...Array(6)].map((_, i) => (
|
|
76
|
+
<div key={i} className="space-y-2">
|
|
77
|
+
<Skeleton className="h-[120px] w-full rounded-lg" />
|
|
78
|
+
<Skeleton className="h-4 w-3/4" />
|
|
79
|
+
<Skeleton className="h-4 w-1/2" />
|
|
80
|
+
</div>
|
|
81
|
+
))}
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
export const Form = () => (
|
|
86
|
+
<div className="space-y-4 max-w-sm">
|
|
87
|
+
<div className="space-y-2">
|
|
88
|
+
<Skeleton className="h-4 w-20" />
|
|
89
|
+
<Skeleton className="h-10 w-full" />
|
|
90
|
+
</div>
|
|
91
|
+
<div className="space-y-2">
|
|
92
|
+
<Skeleton className="h-4 w-20" />
|
|
93
|
+
<Skeleton className="h-10 w-full" />
|
|
94
|
+
</div>
|
|
95
|
+
<div className="space-y-2">
|
|
96
|
+
<Skeleton className="h-4 w-20" />
|
|
97
|
+
<Skeleton className="h-24 w-full" />
|
|
98
|
+
</div>
|
|
99
|
+
<Skeleton className="h-10 w-24" />
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { defineStory, useBoolean, useNumber } from '@djangocfg/playground';
|
|
3
|
+
import { Slider } from './slider';
|
|
4
|
+
import { Label } from './label';
|
|
5
|
+
|
|
6
|
+
export default defineStory({
|
|
7
|
+
title: 'Core/Slider',
|
|
8
|
+
component: Slider,
|
|
9
|
+
description: 'Slider input for selecting numeric values.',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const Interactive = () => {
|
|
13
|
+
const [disabled] = useBoolean('disabled', {
|
|
14
|
+
defaultValue: false,
|
|
15
|
+
label: 'Disabled',
|
|
16
|
+
description: 'Disable slider',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const [max] = useNumber('max', {
|
|
20
|
+
defaultValue: 100,
|
|
21
|
+
min: 10,
|
|
22
|
+
max: 1000,
|
|
23
|
+
label: 'Max Value',
|
|
24
|
+
description: 'Maximum slider value',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const [step] = useNumber('step', {
|
|
28
|
+
defaultValue: 1,
|
|
29
|
+
min: 1,
|
|
30
|
+
max: 10,
|
|
31
|
+
label: 'Step',
|
|
32
|
+
description: 'Step increment',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const [value, setValue] = useState([50]);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div className="max-w-sm space-y-4">
|
|
39
|
+
<div className="space-y-2">
|
|
40
|
+
<div className="flex justify-between">
|
|
41
|
+
<Label>Value</Label>
|
|
42
|
+
<span className="text-sm text-muted-foreground">{value[0]}</span>
|
|
43
|
+
</div>
|
|
44
|
+
<Slider
|
|
45
|
+
value={value}
|
|
46
|
+
onValueChange={setValue}
|
|
47
|
+
max={max}
|
|
48
|
+
step={step}
|
|
49
|
+
disabled={disabled}
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const Default = () => (
|
|
57
|
+
<div className="max-w-sm">
|
|
58
|
+
<Slider defaultValue={[50]} max={100} step={1} />
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
export const WithLabel = () => {
|
|
63
|
+
const [value, setValue] = useState([25]);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<div className="max-w-sm space-y-2">
|
|
67
|
+
<div className="flex justify-between">
|
|
68
|
+
<Label>Volume</Label>
|
|
69
|
+
<span className="text-sm text-muted-foreground">{value[0]}%</span>
|
|
70
|
+
</div>
|
|
71
|
+
<Slider value={value} onValueChange={setValue} max={100} step={1} />
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const Range = () => {
|
|
77
|
+
const [value, setValue] = useState([25, 75]);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<div className="max-w-sm space-y-2">
|
|
81
|
+
<div className="flex justify-between">
|
|
82
|
+
<Label>Price Range</Label>
|
|
83
|
+
<span className="text-sm text-muted-foreground">
|
|
84
|
+
${value[0]} - ${value[1]}
|
|
85
|
+
</span>
|
|
86
|
+
</div>
|
|
87
|
+
<Slider value={value} onValueChange={setValue} max={100} step={1} />
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const Steps = () => (
|
|
93
|
+
<div className="max-w-sm space-y-6">
|
|
94
|
+
<div className="space-y-2">
|
|
95
|
+
<Label>Step: 1</Label>
|
|
96
|
+
<Slider defaultValue={[50]} max={100} step={1} />
|
|
97
|
+
</div>
|
|
98
|
+
<div className="space-y-2">
|
|
99
|
+
<Label>Step: 10</Label>
|
|
100
|
+
<Slider defaultValue={[50]} max={100} step={10} />
|
|
101
|
+
</div>
|
|
102
|
+
<div className="space-y-2">
|
|
103
|
+
<Label>Step: 25</Label>
|
|
104
|
+
<Slider defaultValue={[50]} max={100} step={25} />
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
export const Disabled = () => (
|
|
110
|
+
<div className="max-w-sm">
|
|
111
|
+
<Slider defaultValue={[50]} max={100} disabled />
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { defineStory, useSelect } from '@djangocfg/playground';
|
|
2
|
+
import { Spinner } from './spinner';
|
|
3
|
+
|
|
4
|
+
export default defineStory({
|
|
5
|
+
title: 'Core/Spinner',
|
|
6
|
+
component: Spinner,
|
|
7
|
+
description: 'Loading spinner indicator.',
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const Interactive = () => {
|
|
11
|
+
const [size] = useSelect('size', {
|
|
12
|
+
options: ['sm', 'md', 'lg'] as const,
|
|
13
|
+
defaultValue: 'md',
|
|
14
|
+
label: 'Size',
|
|
15
|
+
description: 'Spinner size',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const sizeClasses = {
|
|
19
|
+
sm: 'h-4 w-4',
|
|
20
|
+
md: 'h-6 w-6',
|
|
21
|
+
lg: 'h-10 w-10',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return <Spinner className={sizeClasses[size]} />;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const Default = () => <Spinner />;
|
|
28
|
+
|
|
29
|
+
export const Sizes = () => (
|
|
30
|
+
<div className="flex items-center gap-4">
|
|
31
|
+
<Spinner className="h-4 w-4" />
|
|
32
|
+
<Spinner className="h-6 w-6" />
|
|
33
|
+
<Spinner className="h-8 w-8" />
|
|
34
|
+
<Spinner className="h-10 w-10" />
|
|
35
|
+
<Spinner className="h-12 w-12" />
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export const InButton = () => (
|
|
40
|
+
<button className="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-primary text-primary-foreground">
|
|
41
|
+
<Spinner className="h-4 w-4" />
|
|
42
|
+
Loading...
|
|
43
|
+
</button>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
export const Centered = () => (
|
|
47
|
+
<div className="flex items-center justify-center h-40 border rounded-lg">
|
|
48
|
+
<Spinner className="h-8 w-8" />
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
export const WithText = () => (
|
|
53
|
+
<div className="flex flex-col items-center gap-2">
|
|
54
|
+
<Spinner className="h-8 w-8" />
|
|
55
|
+
<span className="text-sm text-muted-foreground">Loading data...</span>
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export const FullPage = () => (
|
|
60
|
+
<div className="fixed inset-0 flex items-center justify-center bg-background/80 backdrop-blur-sm">
|
|
61
|
+
<div className="flex flex-col items-center gap-2">
|
|
62
|
+
<Spinner className="h-10 w-10" />
|
|
63
|
+
<span className="text-sm">Please wait...</span>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { defineStory, useBoolean } from '@djangocfg/playground';
|
|
3
|
+
import { Switch } from './switch';
|
|
4
|
+
import { Label } from './label';
|
|
5
|
+
|
|
6
|
+
export default defineStory({
|
|
7
|
+
title: 'Core/Switch',
|
|
8
|
+
component: Switch,
|
|
9
|
+
description: 'Toggle switch for on/off states.',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const Interactive = () => {
|
|
13
|
+
const [disabled] = useBoolean('disabled', {
|
|
14
|
+
defaultValue: false,
|
|
15
|
+
label: 'Disabled',
|
|
16
|
+
description: 'Disable switch',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div className="flex items-center space-x-2">
|
|
21
|
+
<Switch id="airplane-mode" disabled={disabled} />
|
|
22
|
+
<Label htmlFor="airplane-mode">Airplane Mode</Label>
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const Default = () => (
|
|
28
|
+
<div className="flex items-center space-x-2">
|
|
29
|
+
<Switch id="default" />
|
|
30
|
+
<Label htmlFor="default">Default switch</Label>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export const Checked = () => (
|
|
35
|
+
<div className="flex items-center space-x-2">
|
|
36
|
+
<Switch id="checked" defaultChecked />
|
|
37
|
+
<Label htmlFor="checked">Checked by default</Label>
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export const Disabled = () => (
|
|
42
|
+
<div className="space-y-4">
|
|
43
|
+
<div className="flex items-center space-x-2">
|
|
44
|
+
<Switch id="disabled-off" disabled />
|
|
45
|
+
<Label htmlFor="disabled-off">Disabled off</Label>
|
|
46
|
+
</div>
|
|
47
|
+
<div className="flex items-center space-x-2">
|
|
48
|
+
<Switch id="disabled-on" disabled defaultChecked />
|
|
49
|
+
<Label htmlFor="disabled-on">Disabled on</Label>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
export const Settings = () => {
|
|
55
|
+
const [settings, setSettings] = useState({
|
|
56
|
+
notifications: true,
|
|
57
|
+
darkMode: false,
|
|
58
|
+
autoSave: true,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="space-y-6 max-w-sm">
|
|
63
|
+
<div className="flex items-center justify-between">
|
|
64
|
+
<div>
|
|
65
|
+
<Label htmlFor="notifications" className="block">Notifications</Label>
|
|
66
|
+
<span className="text-sm text-muted-foreground">Receive push notifications</span>
|
|
67
|
+
</div>
|
|
68
|
+
<Switch
|
|
69
|
+
id="notifications"
|
|
70
|
+
checked={settings.notifications}
|
|
71
|
+
onCheckedChange={(checked) => setSettings({ ...settings, notifications: checked })}
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
<div className="flex items-center justify-between">
|
|
75
|
+
<div>
|
|
76
|
+
<Label htmlFor="darkMode" className="block">Dark Mode</Label>
|
|
77
|
+
<span className="text-sm text-muted-foreground">Use dark theme</span>
|
|
78
|
+
</div>
|
|
79
|
+
<Switch
|
|
80
|
+
id="darkMode"
|
|
81
|
+
checked={settings.darkMode}
|
|
82
|
+
onCheckedChange={(checked) => setSettings({ ...settings, darkMode: checked })}
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
<div className="flex items-center justify-between">
|
|
86
|
+
<div>
|
|
87
|
+
<Label htmlFor="autoSave" className="block">Auto Save</Label>
|
|
88
|
+
<span className="text-sm text-muted-foreground">Save changes automatically</span>
|
|
89
|
+
</div>
|
|
90
|
+
<Switch
|
|
91
|
+
id="autoSave"
|
|
92
|
+
checked={settings.autoSave}
|
|
93
|
+
onCheckedChange={(checked) => setSettings({ ...settings, autoSave: checked })}
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
};
|