@djangocfg/ui-core 2.1.381 → 2.1.383

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 (78) hide show
  1. package/README.md +85 -21
  2. package/package.json +5 -12
  3. package/src/components/boundary/Boundary.tsx +204 -33
  4. package/src/components/boundary/README.md +249 -0
  5. package/src/components/boundary/index.ts +9 -2
  6. package/src/components/index.ts +9 -2
  7. package/src/components/select/combobox.tsx +47 -19
  8. package/src/hooks/audio/createSoundBus.ts +172 -0
  9. package/src/hooks/audio/index.ts +21 -0
  10. package/src/hooks/audio/useAudioPrefs.ts +91 -0
  11. package/src/hooks/audio/useNotificationSounds.ts +271 -0
  12. package/src/hooks/audio/useSoundEffect.ts +78 -0
  13. package/src/hooks/hotkey/formatHotkey.ts +96 -0
  14. package/src/hooks/hotkey/index.ts +10 -0
  15. package/src/hooks/hotkey/useHotkey.ts +106 -34
  16. package/src/hooks/hotkey/useHotkeyChord.ts +96 -0
  17. package/src/hooks/hotkey/useHotkeyHelp.ts +68 -0
  18. package/src/hooks/index.ts +1 -0
  19. package/src/components/boundary/boundary.story.tsx +0 -109
  20. package/src/components/data/avatar/avatar.story.tsx +0 -115
  21. package/src/components/data/badge/badge.story.tsx +0 -56
  22. package/src/components/data/calendar/calendar.story.tsx +0 -127
  23. package/src/components/data/carousel/carousel.story.tsx +0 -122
  24. package/src/components/data/progress/progress.story.tsx +0 -97
  25. package/src/components/data/table/table.story.tsx +0 -148
  26. package/src/components/data/toggle/toggle.story.tsx +0 -104
  27. package/src/components/data/toggle-group/toggle-group.story.tsx +0 -118
  28. package/src/components/feedback/alert/alert.story.tsx +0 -77
  29. package/src/components/feedback/empty/empty.story.tsx +0 -115
  30. package/src/components/feedback/preloader/preloader.story.tsx +0 -86
  31. package/src/components/feedback/spinner/spinner.story.tsx +0 -66
  32. package/src/components/forms/button/button.story.tsx +0 -116
  33. package/src/components/forms/button-download/button-download.story.tsx +0 -112
  34. package/src/components/forms/button-group/button-group.story.tsx +0 -79
  35. package/src/components/forms/checkbox/checkbox.story.tsx +0 -89
  36. package/src/components/forms/input/input.story.tsx +0 -77
  37. package/src/components/forms/input-group/input-group.story.tsx +0 -119
  38. package/src/components/forms/input-otp/input-otp.story.tsx +0 -105
  39. package/src/components/forms/label/label.story.tsx +0 -52
  40. package/src/components/forms/radio-group/radio-group.story.tsx +0 -113
  41. package/src/components/forms/slider/slider.story.tsx +0 -134
  42. package/src/components/forms/switch/switch.story.tsx +0 -98
  43. package/src/components/forms/textarea/textarea.story.tsx +0 -94
  44. package/src/components/layout/aspect-ratio/aspect-ratio.story.tsx +0 -94
  45. package/src/components/layout/card/card.story.tsx +0 -105
  46. package/src/components/layout/resizable/resizable.story.tsx +0 -119
  47. package/src/components/layout/scroll-area/scroll-area.story.tsx +0 -172
  48. package/src/components/layout/separator/separator.story.tsx +0 -69
  49. package/src/components/layout/skeleton/skeleton.story.tsx +0 -101
  50. package/src/components/navigation/accordion/accordion.story.tsx +0 -110
  51. package/src/components/navigation/collapsible/collapsible.story.tsx +0 -133
  52. package/src/components/navigation/command/command.story.tsx +0 -121
  53. package/src/components/navigation/context-menu/context-menu.story.tsx +0 -125
  54. package/src/components/navigation/dropdown-menu/dropdown-menu.story.tsx +0 -208
  55. package/src/components/navigation/menubar/menubar.story.tsx +0 -152
  56. package/src/components/navigation/navigation-menu/navigation-menu.story.tsx +0 -154
  57. package/src/components/navigation/tabs/tabs.story.tsx +0 -98
  58. package/src/components/overlay/alert-dialog/alert-dialog.story.tsx +0 -104
  59. package/src/components/overlay/dialog/dialog.story.tsx +0 -212
  60. package/src/components/overlay/drawer/drawer.story.tsx +0 -359
  61. package/src/components/overlay/hover-card/hover-card.story.tsx +0 -102
  62. package/src/components/overlay/popover/popover.story.tsx +0 -127
  63. package/src/components/overlay/responsive-sheet/responsive-sheet.story.tsx +0 -117
  64. package/src/components/overlay/sheet/sheet.story.tsx +0 -148
  65. package/src/components/overlay/tooltip/tooltip.story.tsx +0 -139
  66. package/src/components/select/combobox-async.story.tsx +0 -215
  67. package/src/components/select/combobox.story.tsx +0 -226
  68. package/src/components/select/country-select.story.tsx +0 -261
  69. package/src/components/select/language-select.story.tsx +0 -264
  70. package/src/components/select/multi-select.story.tsx +0 -122
  71. package/src/components/select/select.story.tsx +0 -112
  72. package/src/components/specialized/copy/copy.story.tsx +0 -77
  73. package/src/components/specialized/flag/flag.story.tsx +0 -82
  74. package/src/components/specialized/image-with-fallback/image-with-fallback.story.tsx +0 -105
  75. package/src/components/specialized/kbd/kbd.story.tsx +0 -113
  76. package/src/lib/dialog-service/dialog-service.story.tsx +0 -263
  77. package/src/stories/index.ts +0 -28
  78. package/src/styles/theme/theme-tokens.story.tsx +0 -157
@@ -1,115 +0,0 @@
1
- import { defineStory } from '@djangocfg/playground';
2
- import {
3
- Empty,
4
- EmptyHeader,
5
- EmptyTitle,
6
- EmptyDescription,
7
- EmptyContent,
8
- EmptyMedia,
9
- } from '.';
10
- import { Button } from '../../forms/button';
11
- import { Inbox, Search, FileQuestion, Plus, RefreshCw } from 'lucide-react';
12
-
13
- export default defineStory({
14
- title: 'Core/Empty',
15
- component: Empty,
16
- description: 'Empty state placeholder for no content.',
17
- });
18
-
19
- export const Default = () => (
20
- <Empty className="max-w-md mx-auto py-10">
21
- <EmptyMedia>
22
- <Inbox className="h-12 w-12 text-muted-foreground" />
23
- </EmptyMedia>
24
- <EmptyHeader>
25
- <EmptyTitle>No items</EmptyTitle>
26
- <EmptyDescription>
27
- You don't have any items yet. Create your first one to get started.
28
- </EmptyDescription>
29
- </EmptyHeader>
30
- <EmptyContent>
31
- <Button>
32
- <Plus className="mr-2 h-4 w-4" />
33
- Create Item
34
- </Button>
35
- </EmptyContent>
36
- </Empty>
37
- );
38
-
39
- export const SearchNoResults = () => (
40
- <Empty className="max-w-md mx-auto py-10">
41
- <EmptyMedia>
42
- <Search className="h-12 w-12 text-muted-foreground" />
43
- </EmptyMedia>
44
- <EmptyHeader>
45
- <EmptyTitle>No results found</EmptyTitle>
46
- <EmptyDescription>
47
- We couldn't find anything matching your search. Try adjusting your filters.
48
- </EmptyDescription>
49
- </EmptyHeader>
50
- <EmptyContent>
51
- <Button variant="outline">Clear filters</Button>
52
- </EmptyContent>
53
- </Empty>
54
- );
55
-
56
- export const Error = () => (
57
- <Empty className="max-w-md mx-auto py-10">
58
- <EmptyMedia>
59
- <FileQuestion className="h-12 w-12 text-muted-foreground" />
60
- </EmptyMedia>
61
- <EmptyHeader>
62
- <EmptyTitle>Something went wrong</EmptyTitle>
63
- <EmptyDescription>
64
- We encountered an error while loading the data. Please try again.
65
- </EmptyDescription>
66
- </EmptyHeader>
67
- <EmptyContent>
68
- <Button variant="outline">
69
- <RefreshCw className="mr-2 h-4 w-4" />
70
- Retry
71
- </Button>
72
- </EmptyContent>
73
- </Empty>
74
- );
75
-
76
- export const NoNotifications = () => (
77
- <Empty className="max-w-sm mx-auto py-8">
78
- <EmptyMedia>
79
- <Inbox className="h-10 w-10 text-muted-foreground" />
80
- </EmptyMedia>
81
- <EmptyHeader>
82
- <EmptyTitle>All caught up!</EmptyTitle>
83
- <EmptyDescription>
84
- You have no new notifications.
85
- </EmptyDescription>
86
- </EmptyHeader>
87
- </Empty>
88
- );
89
-
90
- export const Simple = () => (
91
- <Empty className="max-w-xs mx-auto py-6">
92
- <EmptyHeader>
93
- <EmptyTitle>No data</EmptyTitle>
94
- <EmptyDescription>
95
- Start by adding some data.
96
- </EmptyDescription>
97
- </EmptyHeader>
98
- </Empty>
99
- );
100
-
101
- export const InCard = () => (
102
- <div className="rounded-lg border p-6">
103
- <Empty>
104
- <EmptyMedia>
105
- <Inbox className="h-8 w-8 text-muted-foreground" />
106
- </EmptyMedia>
107
- <EmptyHeader>
108
- <EmptyTitle className="text-base">Empty inbox</EmptyTitle>
109
- <EmptyDescription className="text-sm">
110
- No messages to display
111
- </EmptyDescription>
112
- </EmptyHeader>
113
- </Empty>
114
- </div>
115
- );
@@ -1,86 +0,0 @@
1
- import { defineStory, useSelect, useBoolean } from '@djangocfg/playground';
2
- import { Preloader, PreloaderSkeleton } from '.';
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
- );
@@ -1,66 +0,0 @@
1
- import { defineStory, useSelect } from '@djangocfg/playground';
2
- import { Spinner } from '.';
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
- );
@@ -1,116 +0,0 @@
1
- import { defineStory, useSelect, useBoolean } from '@djangocfg/playground';
2
- import { Mail, Send, Loader2, ChevronRight, Plus, Trash2 } from 'lucide-react';
3
- import { Button, ButtonLink } from '.';
4
-
5
- export default defineStory({
6
- title: 'Core/Button',
7
- component: Button,
8
- description: 'Versatile button component with multiple variants and sizes.',
9
- });
10
-
11
- export const Interactive = () => {
12
- const [variant] = useSelect('variant', {
13
- options: ['default', 'secondary', 'destructive', 'outline', 'ghost', 'link'] as const,
14
- defaultValue: 'default',
15
- label: 'Variant',
16
- description: 'Button style variant',
17
- });
18
-
19
- const [size] = useSelect('size', {
20
- options: ['xs', 'sm', 'default', 'lg', 'huge', 'icon'] as const,
21
- defaultValue: 'default',
22
- label: 'Size',
23
- description: 'Button size',
24
- });
25
-
26
- const [loading] = useBoolean('loading', {
27
- defaultValue: false,
28
- label: 'Loading',
29
- description: 'Show loading spinner',
30
- });
31
-
32
- const [disabled] = useBoolean('disabled', {
33
- defaultValue: false,
34
- label: 'Disabled',
35
- description: 'Disable button',
36
- });
37
-
38
- return (
39
- <div className="flex flex-wrap gap-4 items-center">
40
- <Button variant={variant} size={size} loading={loading} disabled={disabled}>
41
- {size === 'icon' ? <Plus /> : 'Button'}
42
- </Button>
43
- <Button variant={variant} size={size} loading={loading} disabled={disabled}>
44
- <Mail />
45
- {size !== 'icon' && 'With Icon'}
46
- </Button>
47
- </div>
48
- );
49
- };
50
-
51
- export const Variants = () => (
52
- <div className="flex flex-wrap gap-4">
53
- <Button variant="default">Default</Button>
54
- <Button variant="secondary">Secondary</Button>
55
- <Button variant="destructive">Destructive</Button>
56
- <Button variant="outline">Outline</Button>
57
- <Button variant="ghost">Ghost</Button>
58
- <Button variant="link">Link</Button>
59
- </div>
60
- );
61
-
62
- export const Sizes = () => (
63
- <div className="flex flex-wrap gap-4 items-center">
64
- <Button size="xs">Extra Small</Button>
65
- <Button size="sm">Small</Button>
66
- <Button size="default">Default</Button>
67
- <Button size="lg">Large</Button>
68
- <Button size="huge">Huge</Button>
69
- <Button size="icon"><Plus /></Button>
70
- </div>
71
- );
72
-
73
- export const WithIcons = () => (
74
- <div className="flex flex-wrap gap-4">
75
- <Button>
76
- <Mail />
77
- Login with Email
78
- </Button>
79
- <Button variant="secondary">
80
- Send
81
- <Send />
82
- </Button>
83
- <Button variant="outline">
84
- Next
85
- <ChevronRight />
86
- </Button>
87
- <Button variant="destructive">
88
- <Trash2 />
89
- Delete
90
- </Button>
91
- </div>
92
- );
93
-
94
- export const Loading = () => (
95
- <div className="flex flex-wrap gap-4">
96
- <Button loading>Loading...</Button>
97
- <Button loading variant="secondary">Processing</Button>
98
- <Button loading variant="outline">Please wait</Button>
99
- </div>
100
- );
101
-
102
- export const Disabled = () => (
103
- <div className="flex flex-wrap gap-4">
104
- <Button disabled>Default</Button>
105
- <Button disabled variant="secondary">Secondary</Button>
106
- <Button disabled variant="outline">Outline</Button>
107
- </div>
108
- );
109
-
110
- export const AsLink = () => (
111
- <div className="flex flex-wrap gap-4">
112
- <ButtonLink href="https://example.com">External Link</ButtonLink>
113
- <ButtonLink href="/dashboard" variant="secondary">Dashboard</ButtonLink>
114
- <ButtonLink href="/settings" variant="outline">Settings</ButtonLink>
115
- </div>
116
- );
@@ -1,112 +0,0 @@
1
- import { defineStory, useBoolean } from '@djangocfg/playground';
2
- import { DownloadButton } from '.';
3
-
4
- export default defineStory({
5
- title: 'Core/DownloadButton',
6
- component: DownloadButton,
7
- description: 'Button with download functionality and status indicators.',
8
- });
9
-
10
- export const Interactive = () => {
11
- const [showStatus] = useBoolean('showStatus', {
12
- defaultValue: true,
13
- label: 'Show Status',
14
- description: 'Show loading/success/error icons',
15
- });
16
-
17
- return (
18
- <DownloadButton
19
- url="https://example.com/file.pdf"
20
- filename="document.pdf"
21
- showStatus={showStatus}
22
- >
23
- Download PDF
24
- </DownloadButton>
25
- );
26
- };
27
-
28
- export const Default = () => (
29
- <DownloadButton
30
- url="https://example.com/file.pdf"
31
- filename="document.pdf"
32
- >
33
- Download File
34
- </DownloadButton>
35
- );
36
-
37
- export const IconOnly = () => (
38
- <DownloadButton
39
- url="https://example.com/file.pdf"
40
- filename="document.pdf"
41
- size="icon"
42
- />
43
- );
44
-
45
- export const Variants = () => (
46
- <div className="flex gap-4">
47
- <DownloadButton
48
- url="https://example.com/file.pdf"
49
- variant="default"
50
- >
51
- Default
52
- </DownloadButton>
53
- <DownloadButton
54
- url="https://example.com/file.pdf"
55
- variant="outline"
56
- >
57
- Outline
58
- </DownloadButton>
59
- <DownloadButton
60
- url="https://example.com/file.pdf"
61
- variant="ghost"
62
- >
63
- Ghost
64
- </DownloadButton>
65
- </div>
66
- );
67
-
68
- export const Sizes = () => (
69
- <div className="flex items-center gap-4">
70
- <DownloadButton url="https://example.com/file.pdf" size="sm">
71
- Small
72
- </DownloadButton>
73
- <DownloadButton url="https://example.com/file.pdf" size="default">
74
- Default
75
- </DownloadButton>
76
- <DownloadButton url="https://example.com/file.pdf" size="lg">
77
- Large
78
- </DownloadButton>
79
- </div>
80
- );
81
-
82
- export const WithCallbacks = () => (
83
- <DownloadButton
84
- url="https://example.com/file.pdf"
85
- filename="report.pdf"
86
- onDownloadStart={() => console.log('Download started')}
87
- onDownloadComplete={(name) => console.log(`Downloaded: ${name}`)}
88
- onDownloadError={(err) => console.error('Error:', err)}
89
- >
90
- Download with Callbacks
91
- </DownloadButton>
92
- );
93
-
94
- export const PostRequest = () => (
95
- <DownloadButton
96
- url="https://api.example.com/export"
97
- method="POST"
98
- body={{ format: 'pdf', includeImages: true }}
99
- filename="export.pdf"
100
- >
101
- Export as PDF
102
- </DownloadButton>
103
- );
104
-
105
- export const DisabledStatus = () => (
106
- <DownloadButton
107
- url="https://example.com/file.pdf"
108
- showStatus={false}
109
- >
110
- No Status Icons
111
- </DownloadButton>
112
- );
@@ -1,79 +0,0 @@
1
- import { defineStory } from '@djangocfg/playground';
2
- import { ButtonGroup, ButtonGroupSeparator, ButtonGroupText } from '.';
3
- import { Button } from '../../forms/button';
4
- import { Bold, Italic, Underline, AlignLeft, AlignCenter, AlignRight, ChevronDown } from 'lucide-react';
5
-
6
- export default defineStory({
7
- title: 'Core/ButtonGroup',
8
- component: ButtonGroup,
9
- description: 'Group of buttons with connected styling.',
10
- });
11
-
12
- export const Default = () => (
13
- <ButtonGroup>
14
- <Button variant="outline">First</Button>
15
- <Button variant="outline">Second</Button>
16
- <Button variant="outline">Third</Button>
17
- </ButtonGroup>
18
- );
19
-
20
- export const TextFormatting = () => (
21
- <ButtonGroup>
22
- <Button variant="outline" size="icon">
23
- <Bold className="h-4 w-4" />
24
- </Button>
25
- <Button variant="outline" size="icon">
26
- <Italic className="h-4 w-4" />
27
- </Button>
28
- <Button variant="outline" size="icon">
29
- <Underline className="h-4 w-4" />
30
- </Button>
31
- </ButtonGroup>
32
- );
33
-
34
- export const Alignment = () => (
35
- <ButtonGroup>
36
- <Button variant="outline" size="icon">
37
- <AlignLeft className="h-4 w-4" />
38
- </Button>
39
- <Button variant="outline" size="icon">
40
- <AlignCenter className="h-4 w-4" />
41
- </Button>
42
- <Button variant="outline" size="icon">
43
- <AlignRight className="h-4 w-4" />
44
- </Button>
45
- </ButtonGroup>
46
- );
47
-
48
- export const WithSeparator = () => (
49
- <ButtonGroup>
50
- <Button variant="outline">Edit</Button>
51
- <ButtonGroupSeparator />
52
- <Button variant="outline" size="icon">
53
- <ChevronDown className="h-4 w-4" />
54
- </Button>
55
- </ButtonGroup>
56
- );
57
-
58
- export const WithText = () => (
59
- <ButtonGroup>
60
- <ButtonGroupText>Label</ButtonGroupText>
61
- <Button variant="outline">Action</Button>
62
- </ButtonGroup>
63
- );
64
-
65
- export const Vertical = () => (
66
- <ButtonGroup orientation="vertical">
67
- <Button variant="outline">Top</Button>
68
- <Button variant="outline">Middle</Button>
69
- <Button variant="outline">Bottom</Button>
70
- </ButtonGroup>
71
- );
72
-
73
- export const Mixed = () => (
74
- <ButtonGroup>
75
- <Button variant="default">Primary</Button>
76
- <Button variant="outline">Secondary</Button>
77
- <Button variant="ghost">Tertiary</Button>
78
- </ButtonGroup>
79
- );
@@ -1,89 +0,0 @@
1
- import { useState } from 'react';
2
- import { defineStory, useBoolean } from '@djangocfg/playground';
3
- import { Checkbox } from '.';
4
- import { Label } from '../../forms/label';
5
-
6
- export default defineStory({
7
- title: 'Core/Checkbox',
8
- component: Checkbox,
9
- description: 'Checkbox input for boolean selections.',
10
- });
11
-
12
- export const Interactive = () => {
13
- const [disabled] = useBoolean('disabled', {
14
- defaultValue: false,
15
- label: 'Disabled',
16
- description: 'Disable checkbox',
17
- });
18
-
19
- return (
20
- <div className="flex items-center space-x-2">
21
- <Checkbox id="terms" disabled={disabled} />
22
- <Label htmlFor="terms">Accept terms and conditions</Label>
23
- </div>
24
- );
25
- };
26
-
27
- export const Default = () => (
28
- <div className="flex items-center space-x-2">
29
- <Checkbox id="default" />
30
- <Label htmlFor="default">Default checkbox</Label>
31
- </div>
32
- );
33
-
34
- export const Checked = () => (
35
- <div className="flex items-center space-x-2">
36
- <Checkbox 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
- <Checkbox id="disabled-unchecked" disabled />
45
- <Label htmlFor="disabled-unchecked">Disabled unchecked</Label>
46
- </div>
47
- <div className="flex items-center space-x-2">
48
- <Checkbox id="disabled-checked" disabled defaultChecked />
49
- <Label htmlFor="disabled-checked">Disabled checked</Label>
50
- </div>
51
- </div>
52
- );
53
-
54
- export const WithForm = () => {
55
- const [items, setItems] = useState({
56
- notifications: true,
57
- marketing: false,
58
- updates: true,
59
- });
60
-
61
- return (
62
- <div className="space-y-4">
63
- <div className="flex items-center space-x-2">
64
- <Checkbox
65
- id="notifications"
66
- checked={items.notifications}
67
- onCheckedChange={(checked) => setItems({ ...items, notifications: !!checked })}
68
- />
69
- <Label htmlFor="notifications">Receive notifications</Label>
70
- </div>
71
- <div className="flex items-center space-x-2">
72
- <Checkbox
73
- id="marketing"
74
- checked={items.marketing}
75
- onCheckedChange={(checked) => setItems({ ...items, marketing: !!checked })}
76
- />
77
- <Label htmlFor="marketing">Receive marketing emails</Label>
78
- </div>
79
- <div className="flex items-center space-x-2">
80
- <Checkbox
81
- id="updates"
82
- checked={items.updates}
83
- onCheckedChange={(checked) => setItems({ ...items, updates: !!checked })}
84
- />
85
- <Label htmlFor="updates">Receive product updates</Label>
86
- </div>
87
- </div>
88
- );
89
- };