@djangocfg/ui-core 2.1.120 → 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,89 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { defineStory, useBoolean } from '@djangocfg/playground';
|
|
3
|
+
import { Checkbox } from './checkbox';
|
|
4
|
+
import { Label } from './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
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { defineStory } from '@djangocfg/playground';
|
|
3
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './collapsible';
|
|
4
|
+
import { Button } from './button';
|
|
5
|
+
import { ChevronsUpDown } from 'lucide-react';
|
|
6
|
+
|
|
7
|
+
export default defineStory({
|
|
8
|
+
title: 'Core/Collapsible',
|
|
9
|
+
component: Collapsible,
|
|
10
|
+
description: 'Expandable/collapsible content section.',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const Default = () => {
|
|
14
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Collapsible
|
|
18
|
+
open={isOpen}
|
|
19
|
+
onOpenChange={setIsOpen}
|
|
20
|
+
className="w-[350px] space-y-2"
|
|
21
|
+
>
|
|
22
|
+
<div className="flex items-center justify-between space-x-4 px-4">
|
|
23
|
+
<h4 className="text-sm font-semibold">
|
|
24
|
+
@peduarte starred 3 repositories
|
|
25
|
+
</h4>
|
|
26
|
+
<CollapsibleTrigger asChild>
|
|
27
|
+
<Button variant="ghost" size="sm" className="w-9 p-0">
|
|
28
|
+
<ChevronsUpDown className="h-4 w-4" />
|
|
29
|
+
<span className="sr-only">Toggle</span>
|
|
30
|
+
</Button>
|
|
31
|
+
</CollapsibleTrigger>
|
|
32
|
+
</div>
|
|
33
|
+
<div className="rounded-md border px-4 py-3 font-mono text-sm">
|
|
34
|
+
@radix-ui/primitives
|
|
35
|
+
</div>
|
|
36
|
+
<CollapsibleContent className="space-y-2">
|
|
37
|
+
<div className="rounded-md border px-4 py-3 font-mono text-sm">
|
|
38
|
+
@radix-ui/colors
|
|
39
|
+
</div>
|
|
40
|
+
<div className="rounded-md border px-4 py-3 font-mono text-sm">
|
|
41
|
+
@stitches/react
|
|
42
|
+
</div>
|
|
43
|
+
</CollapsibleContent>
|
|
44
|
+
</Collapsible>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const OpenByDefault = () => {
|
|
49
|
+
const [isOpen, setIsOpen] = useState(true);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Collapsible
|
|
53
|
+
open={isOpen}
|
|
54
|
+
onOpenChange={setIsOpen}
|
|
55
|
+
className="w-[350px] space-y-2"
|
|
56
|
+
>
|
|
57
|
+
<div className="flex items-center justify-between space-x-4 px-4">
|
|
58
|
+
<h4 className="text-sm font-semibold">Notifications</h4>
|
|
59
|
+
<CollapsibleTrigger asChild>
|
|
60
|
+
<Button variant="ghost" size="sm">
|
|
61
|
+
{isOpen ? 'Hide' : 'Show'}
|
|
62
|
+
</Button>
|
|
63
|
+
</CollapsibleTrigger>
|
|
64
|
+
</div>
|
|
65
|
+
<CollapsibleContent className="space-y-2">
|
|
66
|
+
<div className="rounded-md border px-4 py-3 text-sm">
|
|
67
|
+
You have 3 new notifications
|
|
68
|
+
</div>
|
|
69
|
+
<div className="rounded-md border px-4 py-3 text-sm">
|
|
70
|
+
Your order has been shipped
|
|
71
|
+
</div>
|
|
72
|
+
<div className="rounded-md border px-4 py-3 text-sm">
|
|
73
|
+
New comment on your post
|
|
74
|
+
</div>
|
|
75
|
+
</CollapsibleContent>
|
|
76
|
+
</Collapsible>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const Simple = () => (
|
|
81
|
+
<Collapsible className="w-[350px]">
|
|
82
|
+
<CollapsibleTrigger asChild>
|
|
83
|
+
<Button variant="outline" className="w-full justify-between">
|
|
84
|
+
Can I use this in my project?
|
|
85
|
+
<ChevronsUpDown className="h-4 w-4" />
|
|
86
|
+
</Button>
|
|
87
|
+
</CollapsibleTrigger>
|
|
88
|
+
<CollapsibleContent className="pt-2">
|
|
89
|
+
<p className="text-sm text-muted-foreground px-1">
|
|
90
|
+
Yes! This component is free to use in your personal and commercial projects.
|
|
91
|
+
No attribution required.
|
|
92
|
+
</p>
|
|
93
|
+
</CollapsibleContent>
|
|
94
|
+
</Collapsible>
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
export const Multiple = () => (
|
|
98
|
+
<div className="w-[350px] space-y-2">
|
|
99
|
+
<Collapsible>
|
|
100
|
+
<CollapsibleTrigger asChild>
|
|
101
|
+
<Button variant="ghost" className="w-full justify-between">
|
|
102
|
+
Section 1
|
|
103
|
+
<ChevronsUpDown className="h-4 w-4" />
|
|
104
|
+
</Button>
|
|
105
|
+
</CollapsibleTrigger>
|
|
106
|
+
<CollapsibleContent className="px-4 py-2">
|
|
107
|
+
Content for section 1
|
|
108
|
+
</CollapsibleContent>
|
|
109
|
+
</Collapsible>
|
|
110
|
+
<Collapsible>
|
|
111
|
+
<CollapsibleTrigger asChild>
|
|
112
|
+
<Button variant="ghost" className="w-full justify-between">
|
|
113
|
+
Section 2
|
|
114
|
+
<ChevronsUpDown className="h-4 w-4" />
|
|
115
|
+
</Button>
|
|
116
|
+
</CollapsibleTrigger>
|
|
117
|
+
<CollapsibleContent className="px-4 py-2">
|
|
118
|
+
Content for section 2
|
|
119
|
+
</CollapsibleContent>
|
|
120
|
+
</Collapsible>
|
|
121
|
+
<Collapsible>
|
|
122
|
+
<CollapsibleTrigger asChild>
|
|
123
|
+
<Button variant="ghost" className="w-full justify-between">
|
|
124
|
+
Section 3
|
|
125
|
+
<ChevronsUpDown className="h-4 w-4" />
|
|
126
|
+
</Button>
|
|
127
|
+
</CollapsibleTrigger>
|
|
128
|
+
<CollapsibleContent className="px-4 py-2">
|
|
129
|
+
Content for section 3
|
|
130
|
+
</CollapsibleContent>
|
|
131
|
+
</Collapsible>
|
|
132
|
+
</div>
|
|
133
|
+
);
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { defineStory, useBoolean } from '@djangocfg/playground';
|
|
3
|
+
import { Combobox, type ComboboxOption } from './combobox';
|
|
4
|
+
import { Label } from './label';
|
|
5
|
+
|
|
6
|
+
export default defineStory({
|
|
7
|
+
title: 'Core/Combobox',
|
|
8
|
+
component: Combobox,
|
|
9
|
+
description: 'Searchable select with autocomplete.',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const frameworks: ComboboxOption[] = [
|
|
13
|
+
{ value: 'next.js', label: 'Next.js' },
|
|
14
|
+
{ value: 'sveltekit', label: 'SvelteKit' },
|
|
15
|
+
{ value: 'nuxt.js', label: 'Nuxt.js' },
|
|
16
|
+
{ value: 'remix', label: 'Remix' },
|
|
17
|
+
{ value: 'astro', label: 'Astro' },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const countries: ComboboxOption[] = [
|
|
21
|
+
{ value: 'us', label: 'United States' },
|
|
22
|
+
{ value: 'uk', label: 'United Kingdom' },
|
|
23
|
+
{ value: 'de', label: 'Germany' },
|
|
24
|
+
{ value: 'fr', label: 'France' },
|
|
25
|
+
{ value: 'jp', label: 'Japan' },
|
|
26
|
+
{ value: 'kr', label: 'South Korea' },
|
|
27
|
+
{ value: 'cn', label: 'China' },
|
|
28
|
+
{ value: 'au', label: 'Australia' },
|
|
29
|
+
{ value: 'ca', label: 'Canada' },
|
|
30
|
+
{ value: 'br', label: 'Brazil' },
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
export const Interactive = () => {
|
|
34
|
+
const [value, setValue] = useState('');
|
|
35
|
+
const [disabled] = useBoolean('disabled', {
|
|
36
|
+
defaultValue: false,
|
|
37
|
+
label: 'Disabled',
|
|
38
|
+
description: 'Disable combobox',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div className="max-w-xs space-y-2">
|
|
43
|
+
<Label>Framework</Label>
|
|
44
|
+
<Combobox
|
|
45
|
+
options={frameworks}
|
|
46
|
+
value={value}
|
|
47
|
+
onValueChange={setValue}
|
|
48
|
+
placeholder="Select framework..."
|
|
49
|
+
searchPlaceholder="Search framework..."
|
|
50
|
+
emptyText="No framework found."
|
|
51
|
+
disabled={disabled}
|
|
52
|
+
/>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const Default = () => {
|
|
58
|
+
const [value, setValue] = useState('');
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div className="max-w-xs">
|
|
62
|
+
<Combobox
|
|
63
|
+
options={frameworks}
|
|
64
|
+
value={value}
|
|
65
|
+
onValueChange={setValue}
|
|
66
|
+
placeholder="Select framework..."
|
|
67
|
+
searchPlaceholder="Search framework..."
|
|
68
|
+
emptyText="No framework found."
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const WithDefaultValue = () => {
|
|
75
|
+
const [value, setValue] = useState('next.js');
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div className="max-w-xs">
|
|
79
|
+
<Combobox
|
|
80
|
+
options={frameworks}
|
|
81
|
+
value={value}
|
|
82
|
+
onValueChange={setValue}
|
|
83
|
+
placeholder="Select framework..."
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const Countries = () => {
|
|
90
|
+
const [value, setValue] = useState('');
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div className="max-w-xs space-y-2">
|
|
94
|
+
<Label>Country</Label>
|
|
95
|
+
<Combobox
|
|
96
|
+
options={countries}
|
|
97
|
+
value={value}
|
|
98
|
+
onValueChange={setValue}
|
|
99
|
+
placeholder="Select country..."
|
|
100
|
+
searchPlaceholder="Search countries..."
|
|
101
|
+
emptyText="No country found."
|
|
102
|
+
/>
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const Disabled = () => (
|
|
108
|
+
<div className="max-w-xs">
|
|
109
|
+
<Combobox
|
|
110
|
+
options={frameworks}
|
|
111
|
+
value=""
|
|
112
|
+
onValueChange={() => {}}
|
|
113
|
+
placeholder="Select framework..."
|
|
114
|
+
disabled
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
export const Form = () => {
|
|
120
|
+
const [framework, setFramework] = useState('');
|
|
121
|
+
const [country, setCountry] = useState('');
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<div className="max-w-xs space-y-4">
|
|
125
|
+
<div className="space-y-2">
|
|
126
|
+
<Label>Framework</Label>
|
|
127
|
+
<Combobox
|
|
128
|
+
options={frameworks}
|
|
129
|
+
value={framework}
|
|
130
|
+
onValueChange={setFramework}
|
|
131
|
+
placeholder="Select framework..."
|
|
132
|
+
/>
|
|
133
|
+
</div>
|
|
134
|
+
<div className="space-y-2">
|
|
135
|
+
<Label>Country</Label>
|
|
136
|
+
<Combobox
|
|
137
|
+
options={countries}
|
|
138
|
+
value={country}
|
|
139
|
+
onValueChange={setCountry}
|
|
140
|
+
placeholder="Select country..."
|
|
141
|
+
/>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { defineStory } from '@djangocfg/playground';
|
|
2
|
+
import {
|
|
3
|
+
Command,
|
|
4
|
+
CommandDialog,
|
|
5
|
+
CommandEmpty,
|
|
6
|
+
CommandGroup,
|
|
7
|
+
CommandInput,
|
|
8
|
+
CommandItem,
|
|
9
|
+
CommandList,
|
|
10
|
+
CommandSeparator,
|
|
11
|
+
CommandShortcut,
|
|
12
|
+
} from './command';
|
|
13
|
+
import { useState } from 'react';
|
|
14
|
+
import { Button } from './button';
|
|
15
|
+
import { Calendar, Smile, Calculator, User, CreditCard, Settings } from 'lucide-react';
|
|
16
|
+
|
|
17
|
+
export default defineStory({
|
|
18
|
+
title: 'Core/Command',
|
|
19
|
+
component: Command,
|
|
20
|
+
description: 'Command palette for search and quick actions.',
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const Default = () => (
|
|
24
|
+
<Command className="rounded-lg border shadow-md max-w-md">
|
|
25
|
+
<CommandInput placeholder="Type a command or search..." />
|
|
26
|
+
<CommandList>
|
|
27
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
28
|
+
<CommandGroup heading="Suggestions">
|
|
29
|
+
<CommandItem>
|
|
30
|
+
<Calendar className="mr-2 h-4 w-4" />
|
|
31
|
+
<span>Calendar</span>
|
|
32
|
+
</CommandItem>
|
|
33
|
+
<CommandItem>
|
|
34
|
+
<Smile className="mr-2 h-4 w-4" />
|
|
35
|
+
<span>Search Emoji</span>
|
|
36
|
+
</CommandItem>
|
|
37
|
+
<CommandItem>
|
|
38
|
+
<Calculator className="mr-2 h-4 w-4" />
|
|
39
|
+
<span>Calculator</span>
|
|
40
|
+
</CommandItem>
|
|
41
|
+
</CommandGroup>
|
|
42
|
+
<CommandSeparator />
|
|
43
|
+
<CommandGroup heading="Settings">
|
|
44
|
+
<CommandItem>
|
|
45
|
+
<User className="mr-2 h-4 w-4" />
|
|
46
|
+
<span>Profile</span>
|
|
47
|
+
<CommandShortcut>⌘P</CommandShortcut>
|
|
48
|
+
</CommandItem>
|
|
49
|
+
<CommandItem>
|
|
50
|
+
<CreditCard className="mr-2 h-4 w-4" />
|
|
51
|
+
<span>Billing</span>
|
|
52
|
+
<CommandShortcut>⌘B</CommandShortcut>
|
|
53
|
+
</CommandItem>
|
|
54
|
+
<CommandItem>
|
|
55
|
+
<Settings className="mr-2 h-4 w-4" />
|
|
56
|
+
<span>Settings</span>
|
|
57
|
+
<CommandShortcut>⌘S</CommandShortcut>
|
|
58
|
+
</CommandItem>
|
|
59
|
+
</CommandGroup>
|
|
60
|
+
</CommandList>
|
|
61
|
+
</Command>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
export const Dialog = () => {
|
|
65
|
+
const [open, setOpen] = useState(false);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<>
|
|
69
|
+
<Button onClick={() => setOpen(true)}>
|
|
70
|
+
Open Command Palette
|
|
71
|
+
</Button>
|
|
72
|
+
<CommandDialog open={open} onOpenChange={setOpen}>
|
|
73
|
+
<CommandInput placeholder="Type a command or search..." />
|
|
74
|
+
<CommandList>
|
|
75
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
76
|
+
<CommandGroup heading="Suggestions">
|
|
77
|
+
<CommandItem onSelect={() => setOpen(false)}>
|
|
78
|
+
<Calendar className="mr-2 h-4 w-4" />
|
|
79
|
+
<span>Calendar</span>
|
|
80
|
+
</CommandItem>
|
|
81
|
+
<CommandItem onSelect={() => setOpen(false)}>
|
|
82
|
+
<Smile className="mr-2 h-4 w-4" />
|
|
83
|
+
<span>Search Emoji</span>
|
|
84
|
+
</CommandItem>
|
|
85
|
+
<CommandItem onSelect={() => setOpen(false)}>
|
|
86
|
+
<Calculator className="mr-2 h-4 w-4" />
|
|
87
|
+
<span>Calculator</span>
|
|
88
|
+
</CommandItem>
|
|
89
|
+
</CommandGroup>
|
|
90
|
+
<CommandSeparator />
|
|
91
|
+
<CommandGroup heading="Settings">
|
|
92
|
+
<CommandItem onSelect={() => setOpen(false)}>
|
|
93
|
+
<User className="mr-2 h-4 w-4" />
|
|
94
|
+
<span>Profile</span>
|
|
95
|
+
<CommandShortcut>⌘P</CommandShortcut>
|
|
96
|
+
</CommandItem>
|
|
97
|
+
<CommandItem onSelect={() => setOpen(false)}>
|
|
98
|
+
<Settings className="mr-2 h-4 w-4" />
|
|
99
|
+
<span>Settings</span>
|
|
100
|
+
<CommandShortcut>⌘S</CommandShortcut>
|
|
101
|
+
</CommandItem>
|
|
102
|
+
</CommandGroup>
|
|
103
|
+
</CommandList>
|
|
104
|
+
</CommandDialog>
|
|
105
|
+
</>
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const Simple = () => (
|
|
110
|
+
<Command className="rounded-lg border max-w-sm">
|
|
111
|
+
<CommandInput placeholder="Search..." />
|
|
112
|
+
<CommandList>
|
|
113
|
+
<CommandEmpty>No results.</CommandEmpty>
|
|
114
|
+
<CommandGroup>
|
|
115
|
+
<CommandItem>Item 1</CommandItem>
|
|
116
|
+
<CommandItem>Item 2</CommandItem>
|
|
117
|
+
<CommandItem>Item 3</CommandItem>
|
|
118
|
+
</CommandGroup>
|
|
119
|
+
</CommandList>
|
|
120
|
+
</Command>
|
|
121
|
+
);
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { defineStory } from '@djangocfg/playground';
|
|
3
|
+
import {
|
|
4
|
+
ContextMenu,
|
|
5
|
+
ContextMenuTrigger,
|
|
6
|
+
ContextMenuContent,
|
|
7
|
+
ContextMenuItem,
|
|
8
|
+
ContextMenuSeparator,
|
|
9
|
+
ContextMenuShortcut,
|
|
10
|
+
ContextMenuSub,
|
|
11
|
+
ContextMenuSubTrigger,
|
|
12
|
+
ContextMenuSubContent,
|
|
13
|
+
ContextMenuCheckboxItem,
|
|
14
|
+
ContextMenuRadioGroup,
|
|
15
|
+
ContextMenuRadioItem,
|
|
16
|
+
ContextMenuLabel,
|
|
17
|
+
} from './context-menu';
|
|
18
|
+
|
|
19
|
+
export default defineStory({
|
|
20
|
+
title: 'Core/ContextMenu',
|
|
21
|
+
component: ContextMenu,
|
|
22
|
+
description: 'Right-click context menu.',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const Default = () => (
|
|
26
|
+
<ContextMenu>
|
|
27
|
+
<ContextMenuTrigger className="flex h-40 w-80 items-center justify-center rounded-md border border-dashed text-sm">
|
|
28
|
+
Right click here
|
|
29
|
+
</ContextMenuTrigger>
|
|
30
|
+
<ContextMenuContent className="w-64">
|
|
31
|
+
<ContextMenuItem>
|
|
32
|
+
Back
|
|
33
|
+
<ContextMenuShortcut>⌘[</ContextMenuShortcut>
|
|
34
|
+
</ContextMenuItem>
|
|
35
|
+
<ContextMenuItem disabled>
|
|
36
|
+
Forward
|
|
37
|
+
<ContextMenuShortcut>⌘]</ContextMenuShortcut>
|
|
38
|
+
</ContextMenuItem>
|
|
39
|
+
<ContextMenuItem>
|
|
40
|
+
Reload
|
|
41
|
+
<ContextMenuShortcut>⌘R</ContextMenuShortcut>
|
|
42
|
+
</ContextMenuItem>
|
|
43
|
+
<ContextMenuSeparator />
|
|
44
|
+
<ContextMenuItem>
|
|
45
|
+
Save Page As...
|
|
46
|
+
<ContextMenuShortcut>⌘S</ContextMenuShortcut>
|
|
47
|
+
</ContextMenuItem>
|
|
48
|
+
<ContextMenuItem>Print...</ContextMenuItem>
|
|
49
|
+
</ContextMenuContent>
|
|
50
|
+
</ContextMenu>
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
export const WithSubMenu = () => (
|
|
54
|
+
<ContextMenu>
|
|
55
|
+
<ContextMenuTrigger className="flex h-40 w-80 items-center justify-center rounded-md border border-dashed text-sm">
|
|
56
|
+
Right click here
|
|
57
|
+
</ContextMenuTrigger>
|
|
58
|
+
<ContextMenuContent className="w-64">
|
|
59
|
+
<ContextMenuItem>New Tab</ContextMenuItem>
|
|
60
|
+
<ContextMenuItem>New Window</ContextMenuItem>
|
|
61
|
+
<ContextMenuSeparator />
|
|
62
|
+
<ContextMenuSub>
|
|
63
|
+
<ContextMenuSubTrigger>More Tools</ContextMenuSubTrigger>
|
|
64
|
+
<ContextMenuSubContent className="w-48">
|
|
65
|
+
<ContextMenuItem>Save Page As...</ContextMenuItem>
|
|
66
|
+
<ContextMenuItem>Create Shortcut...</ContextMenuItem>
|
|
67
|
+
<ContextMenuItem>Name Window...</ContextMenuItem>
|
|
68
|
+
<ContextMenuSeparator />
|
|
69
|
+
<ContextMenuItem>Developer Tools</ContextMenuItem>
|
|
70
|
+
</ContextMenuSubContent>
|
|
71
|
+
</ContextMenuSub>
|
|
72
|
+
<ContextMenuSeparator />
|
|
73
|
+
<ContextMenuItem>Settings</ContextMenuItem>
|
|
74
|
+
</ContextMenuContent>
|
|
75
|
+
</ContextMenu>
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
export const WithCheckboxes = () => {
|
|
79
|
+
const [showBookmarks, setShowBookmarks] = useState(true);
|
|
80
|
+
const [showFullUrls, setShowFullUrls] = useState(false);
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<ContextMenu>
|
|
84
|
+
<ContextMenuTrigger className="flex h-40 w-80 items-center justify-center rounded-md border border-dashed text-sm">
|
|
85
|
+
Right click here
|
|
86
|
+
</ContextMenuTrigger>
|
|
87
|
+
<ContextMenuContent className="w-64">
|
|
88
|
+
<ContextMenuCheckboxItem
|
|
89
|
+
checked={showBookmarks}
|
|
90
|
+
onCheckedChange={setShowBookmarks}
|
|
91
|
+
>
|
|
92
|
+
Show Bookmarks Bar
|
|
93
|
+
<ContextMenuShortcut>⌘⇧B</ContextMenuShortcut>
|
|
94
|
+
</ContextMenuCheckboxItem>
|
|
95
|
+
<ContextMenuCheckboxItem
|
|
96
|
+
checked={showFullUrls}
|
|
97
|
+
onCheckedChange={setShowFullUrls}
|
|
98
|
+
>
|
|
99
|
+
Show Full URLs
|
|
100
|
+
</ContextMenuCheckboxItem>
|
|
101
|
+
</ContextMenuContent>
|
|
102
|
+
</ContextMenu>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const WithRadioGroup = () => {
|
|
107
|
+
const [person, setPerson] = useState('pedro');
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<ContextMenu>
|
|
111
|
+
<ContextMenuTrigger className="flex h-40 w-80 items-center justify-center rounded-md border border-dashed text-sm">
|
|
112
|
+
Right click here
|
|
113
|
+
</ContextMenuTrigger>
|
|
114
|
+
<ContextMenuContent className="w-64">
|
|
115
|
+
<ContextMenuLabel>People</ContextMenuLabel>
|
|
116
|
+
<ContextMenuSeparator />
|
|
117
|
+
<ContextMenuRadioGroup value={person} onValueChange={setPerson}>
|
|
118
|
+
<ContextMenuRadioItem value="pedro">Pedro Duarte</ContextMenuRadioItem>
|
|
119
|
+
<ContextMenuRadioItem value="colm">Colm Tuite</ContextMenuRadioItem>
|
|
120
|
+
<ContextMenuRadioItem value="jamie">Jamie Kyle</ContextMenuRadioItem>
|
|
121
|
+
</ContextMenuRadioGroup>
|
|
122
|
+
</ContextMenuContent>
|
|
123
|
+
</ContextMenu>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { defineStory, useSelect } from '@djangocfg/playground';
|
|
2
|
+
import { CopyButton, CopyField } from './copy';
|
|
3
|
+
|
|
4
|
+
export default defineStory({
|
|
5
|
+
title: 'Core/Copy',
|
|
6
|
+
component: CopyButton,
|
|
7
|
+
description: 'Copy to clipboard components.',
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const Button = () => (
|
|
11
|
+
<CopyButton value="Hello, World!" />
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export const ButtonWithText = () => (
|
|
15
|
+
<CopyButton value="npm install @djangocfg/ui-core">
|
|
16
|
+
Copy command
|
|
17
|
+
</CopyButton>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const ButtonVariants = () => (
|
|
21
|
+
<div className="flex gap-2">
|
|
22
|
+
<CopyButton value="Text" variant="default" />
|
|
23
|
+
<CopyButton value="Text" variant="outline" />
|
|
24
|
+
<CopyButton value="Text" variant="ghost" />
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export const ButtonSizes = () => (
|
|
29
|
+
<div className="flex items-center gap-2">
|
|
30
|
+
<CopyButton value="Text" size="sm" />
|
|
31
|
+
<CopyButton value="Text" size="default" />
|
|
32
|
+
<CopyButton value="Text" size="icon" />
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
export const Field = () => (
|
|
37
|
+
<div className="max-w-md">
|
|
38
|
+
<CopyField value="npm install @djangocfg/ui-core" />
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
export const FieldWithLabel = () => (
|
|
43
|
+
<div className="max-w-md space-y-2">
|
|
44
|
+
<label className="text-sm font-medium">Installation command</label>
|
|
45
|
+
<CopyField value="npm install @djangocfg/ui-core" />
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const ApiKey = () => (
|
|
50
|
+
<div className="max-w-md space-y-2">
|
|
51
|
+
<label className="text-sm font-medium">API Key</label>
|
|
52
|
+
<CopyField value="sk-1234567890abcdefghijklmnopqrstuvwxyz" />
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
export const URLs = () => (
|
|
57
|
+
<div className="max-w-lg space-y-4">
|
|
58
|
+
<div className="space-y-2">
|
|
59
|
+
<label className="text-sm font-medium">Share Link</label>
|
|
60
|
+
<CopyField value="https://example.com/share/abc123" />
|
|
61
|
+
</div>
|
|
62
|
+
<div className="space-y-2">
|
|
63
|
+
<label className="text-sm font-medium">Embed Code</label>
|
|
64
|
+
<CopyField value='<iframe src="https://example.com/embed/abc123"></iframe>' />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
export const InCard = () => (
|
|
70
|
+
<div className="rounded-lg border p-4 max-w-md">
|
|
71
|
+
<h4 className="font-medium mb-2">Invite Link</h4>
|
|
72
|
+
<p className="text-sm text-muted-foreground mb-4">
|
|
73
|
+
Share this link with your team members.
|
|
74
|
+
</p>
|
|
75
|
+
<CopyField value="https://app.example.com/invite/team-abc123" />
|
|
76
|
+
</div>
|
|
77
|
+
);
|