@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,77 +0,0 @@
1
- import { defineStory, useSelect, useBoolean } from '@djangocfg/playground';
2
- import { Input } from '.';
3
- import { Label } from '../../forms/label';
4
-
5
- export default defineStory({
6
- title: 'Core/Input',
7
- component: Input,
8
- description: 'Text input component for forms.',
9
- });
10
-
11
- export const Interactive = () => {
12
- const [type] = useSelect('type', {
13
- options: ['text', 'email', 'password', 'number', 'search', 'tel', 'url'] as const,
14
- defaultValue: 'text',
15
- label: 'Type',
16
- description: 'Input type',
17
- });
18
-
19
- const [disabled] = useBoolean('disabled', {
20
- defaultValue: false,
21
- label: 'Disabled',
22
- description: 'Disable input',
23
- });
24
-
25
- return (
26
- <div className="max-w-sm space-y-4">
27
- <div className="space-y-2">
28
- <Label htmlFor="demo">Label</Label>
29
- <Input
30
- id="demo"
31
- type={type}
32
- placeholder={`Enter ${type}...`}
33
- disabled={disabled}
34
- />
35
- </div>
36
- </div>
37
- );
38
- };
39
-
40
- export const Types = () => (
41
- <div className="max-w-sm space-y-4">
42
- <Input type="text" placeholder="Text input" />
43
- <Input type="email" placeholder="Email input" />
44
- <Input type="password" placeholder="Password input" />
45
- <Input type="number" placeholder="Number input" />
46
- <Input type="search" placeholder="Search input" />
47
- </div>
48
- );
49
-
50
- export const WithLabels = () => (
51
- <div className="max-w-sm space-y-4">
52
- <div className="space-y-2">
53
- <Label htmlFor="email">Email</Label>
54
- <Input id="email" type="email" placeholder="Enter your email" />
55
- </div>
56
- <div className="space-y-2">
57
- <Label htmlFor="password">Password</Label>
58
- <Input id="password" type="password" placeholder="Enter password" />
59
- </div>
60
- </div>
61
- );
62
-
63
- export const States = () => (
64
- <div className="max-w-sm space-y-4">
65
- <Input placeholder="Default" />
66
- <Input placeholder="Disabled" disabled />
67
- <Input placeholder="With value" defaultValue="Hello World" />
68
- <Input placeholder="Read only" readOnly defaultValue="Read only value" />
69
- </div>
70
- );
71
-
72
- export const File = () => (
73
- <div className="max-w-sm space-y-2">
74
- <Label htmlFor="file">Upload file</Label>
75
- <Input id="file" type="file" />
76
- </div>
77
- );
@@ -1,119 +0,0 @@
1
- import { defineStory } from '@djangocfg/playground';
2
- import {
3
- InputGroup,
4
- InputGroupAddon,
5
- InputGroupButton,
6
- InputGroupText,
7
- InputGroupInput,
8
- InputGroupTextarea,
9
- } from '.';
10
- import { Search, Mail, Eye, EyeOff, Copy, AtSign } from 'lucide-react';
11
- import { useState } from 'react';
12
- import { Kbd } from '../../specialized/kbd';
13
-
14
- export default defineStory({
15
- title: 'Core/InputGroup',
16
- component: InputGroup,
17
- description: 'Input with addons, buttons, and icons.',
18
- });
19
-
20
- export const WithIcon = () => (
21
- <InputGroup className="max-w-sm">
22
- <InputGroupAddon>
23
- <Search className="h-4 w-4" />
24
- </InputGroupAddon>
25
- <InputGroupInput placeholder="Search..." />
26
- </InputGroup>
27
- );
28
-
29
- export const WithText = () => (
30
- <InputGroup className="max-w-sm">
31
- <InputGroupAddon>
32
- <InputGroupText>https://</InputGroupText>
33
- </InputGroupAddon>
34
- <InputGroupInput placeholder="example.com" />
35
- </InputGroup>
36
- );
37
-
38
- export const WithButton = () => (
39
- <InputGroup className="max-w-sm">
40
- <InputGroupInput placeholder="Enter email" />
41
- <InputGroupAddon align="inline-end">
42
- <InputGroupButton>Subscribe</InputGroupButton>
43
- </InputGroupAddon>
44
- </InputGroup>
45
- );
46
-
47
- export const PasswordToggle = () => {
48
- const [showPassword, setShowPassword] = useState(false);
49
-
50
- return (
51
- <InputGroup className="max-w-sm">
52
- <InputGroupInput
53
- type={showPassword ? 'text' : 'password'}
54
- placeholder="Enter password"
55
- />
56
- <InputGroupAddon align="inline-end">
57
- <InputGroupButton
58
- size="icon-xs"
59
- onClick={() => setShowPassword(!showPassword)}
60
- >
61
- {showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
62
- </InputGroupButton>
63
- </InputGroupAddon>
64
- </InputGroup>
65
- );
66
- };
67
-
68
- export const CopyInput = () => (
69
- <InputGroup className="max-w-md">
70
- <InputGroupInput value="npm install @djangocfg/ui-core" readOnly />
71
- <InputGroupAddon align="inline-end">
72
- <InputGroupButton size="icon-xs">
73
- <Copy className="h-4 w-4" />
74
- </InputGroupButton>
75
- </InputGroupAddon>
76
- </InputGroup>
77
- );
78
-
79
- export const WithKbd = () => (
80
- <InputGroup className="max-w-sm">
81
- <InputGroupAddon>
82
- <Search className="h-4 w-4" />
83
- </InputGroupAddon>
84
- <InputGroupInput placeholder="Search..." />
85
- <InputGroupAddon align="inline-end">
86
- <Kbd size="xs">⌘K</Kbd>
87
- </InputGroupAddon>
88
- </InputGroup>
89
- );
90
-
91
- export const Email = () => (
92
- <InputGroup className="max-w-sm">
93
- <InputGroupAddon>
94
- <AtSign className="h-4 w-4" />
95
- </InputGroupAddon>
96
- <InputGroupInput type="email" placeholder="you@example.com" />
97
- </InputGroup>
98
- );
99
-
100
- export const WithTextarea = () => (
101
- <InputGroup className="max-w-md">
102
- <InputGroupAddon align="block-start">
103
- <InputGroupText>Description</InputGroupText>
104
- </InputGroupAddon>
105
- <InputGroupTextarea placeholder="Enter description..." rows={4} />
106
- </InputGroup>
107
- );
108
-
109
- export const BothSides = () => (
110
- <InputGroup className="max-w-sm">
111
- <InputGroupAddon>
112
- <Mail className="h-4 w-4" />
113
- </InputGroupAddon>
114
- <InputGroupInput placeholder="Enter email" />
115
- <InputGroupAddon align="inline-end">
116
- <InputGroupButton>Send</InputGroupButton>
117
- </InputGroupAddon>
118
- </InputGroup>
119
- );
@@ -1,105 +0,0 @@
1
- import { useState } from 'react';
2
- import { defineStory } from '@djangocfg/playground';
3
- import {
4
- InputOTP,
5
- InputOTPGroup,
6
- InputOTPSlot,
7
- InputOTPSeparator,
8
- } from '.';
9
-
10
- export default defineStory({
11
- title: 'Core/InputOTP',
12
- component: InputOTP,
13
- description: 'One-time password input with individual digit slots.',
14
- });
15
-
16
- export const Default = () => {
17
- const [value, setValue] = useState('');
18
-
19
- return (
20
- <InputOTP maxLength={6} value={value} onChange={setValue}>
21
- <InputOTPGroup>
22
- <InputOTPSlot index={0} />
23
- <InputOTPSlot index={1} />
24
- <InputOTPSlot index={2} />
25
- <InputOTPSlot index={3} />
26
- <InputOTPSlot index={4} />
27
- <InputOTPSlot index={5} />
28
- </InputOTPGroup>
29
- </InputOTP>
30
- );
31
- };
32
-
33
- export const WithSeparator = () => {
34
- const [value, setValue] = useState('');
35
-
36
- return (
37
- <InputOTP maxLength={6} value={value} onChange={setValue}>
38
- <InputOTPGroup>
39
- <InputOTPSlot index={0} />
40
- <InputOTPSlot index={1} />
41
- <InputOTPSlot index={2} />
42
- </InputOTPGroup>
43
- <InputOTPSeparator />
44
- <InputOTPGroup>
45
- <InputOTPSlot index={3} />
46
- <InputOTPSlot index={4} />
47
- <InputOTPSlot index={5} />
48
- </InputOTPGroup>
49
- </InputOTP>
50
- );
51
- };
52
-
53
- export const FourDigits = () => {
54
- const [value, setValue] = useState('');
55
-
56
- return (
57
- <InputOTP maxLength={4} value={value} onChange={setValue}>
58
- <InputOTPGroup>
59
- <InputOTPSlot index={0} />
60
- <InputOTPSlot index={1} />
61
- <InputOTPSlot index={2} />
62
- <InputOTPSlot index={3} />
63
- </InputOTPGroup>
64
- </InputOTP>
65
- );
66
- };
67
-
68
- export const Disabled = () => (
69
- <InputOTP maxLength={6} disabled>
70
- <InputOTPGroup>
71
- <InputOTPSlot index={0} />
72
- <InputOTPSlot index={1} />
73
- <InputOTPSlot index={2} />
74
- <InputOTPSlot index={3} />
75
- <InputOTPSlot index={4} />
76
- <InputOTPSlot index={5} />
77
- </InputOTPGroup>
78
- </InputOTP>
79
- );
80
-
81
- export const WithLabel = () => {
82
- const [value, setValue] = useState('');
83
-
84
- return (
85
- <div className="space-y-2">
86
- <label className="text-sm font-medium">Verification Code</label>
87
- <InputOTP maxLength={6} value={value} onChange={setValue}>
88
- <InputOTPGroup>
89
- <InputOTPSlot index={0} />
90
- <InputOTPSlot index={1} />
91
- <InputOTPSlot index={2} />
92
- </InputOTPGroup>
93
- <InputOTPSeparator />
94
- <InputOTPGroup>
95
- <InputOTPSlot index={3} />
96
- <InputOTPSlot index={4} />
97
- <InputOTPSlot index={5} />
98
- </InputOTPGroup>
99
- </InputOTP>
100
- <p className="text-sm text-muted-foreground">
101
- Enter the 6-digit code sent to your email.
102
- </p>
103
- </div>
104
- );
105
- };
@@ -1,52 +0,0 @@
1
- import { defineStory } from '@djangocfg/playground';
2
- import { Label } from '.';
3
- import { Input } from '../../forms/input';
4
- import { Checkbox } from '../../forms/checkbox';
5
-
6
- export default defineStory({
7
- title: 'Core/Label',
8
- component: Label,
9
- description: 'Accessible label for form controls.',
10
- });
11
-
12
- export const Default = () => <Label>Email address</Label>;
13
-
14
- export const WithInput = () => (
15
- <div className="max-w-sm space-y-2">
16
- <Label htmlFor="email">Email</Label>
17
- <Input id="email" type="email" placeholder="you@example.com" />
18
- </div>
19
- );
20
-
21
- export const WithCheckbox = () => (
22
- <div className="flex items-center space-x-2">
23
- <Checkbox id="terms" />
24
- <Label htmlFor="terms">Accept terms and conditions</Label>
25
- </div>
26
- );
27
-
28
- export const Required = () => (
29
- <div className="max-w-sm space-y-2">
30
- <Label htmlFor="name">
31
- Name <span className="text-destructive">*</span>
32
- </Label>
33
- <Input id="name" placeholder="Enter your name" />
34
- </div>
35
- );
36
-
37
- export const WithDescription = () => (
38
- <div className="max-w-sm space-y-1">
39
- <Label htmlFor="bio">Bio</Label>
40
- <p className="text-sm text-muted-foreground">
41
- Tell us a little about yourself.
42
- </p>
43
- <Input id="bio" placeholder="I am..." />
44
- </div>
45
- );
46
-
47
- export const Disabled = () => (
48
- <div className="max-w-sm space-y-2">
49
- <Label htmlFor="disabled" className="opacity-50">Disabled field</Label>
50
- <Input id="disabled" disabled placeholder="Cannot edit" />
51
- </div>
52
- );
@@ -1,113 +0,0 @@
1
- import { defineStory, useBoolean } from '@djangocfg/playground';
2
- import { RadioGroup, RadioGroupItem } from '.';
3
- import { Label } from '../../forms/label';
4
-
5
- export default defineStory({
6
- title: 'Core/Radio Group',
7
- component: RadioGroup,
8
- description: 'Radio button group for single selection.',
9
- });
10
-
11
- export const Interactive = () => {
12
- const [disabled] = useBoolean('disabled', {
13
- defaultValue: false,
14
- label: 'Disabled',
15
- description: 'Disable radio group',
16
- });
17
-
18
- return (
19
- <RadioGroup defaultValue="option-1" disabled={disabled}>
20
- <div className="flex items-center space-x-2">
21
- <RadioGroupItem value="option-1" id="option-1" />
22
- <Label htmlFor="option-1">Option 1</Label>
23
- </div>
24
- <div className="flex items-center space-x-2">
25
- <RadioGroupItem value="option-2" id="option-2" />
26
- <Label htmlFor="option-2">Option 2</Label>
27
- </div>
28
- <div className="flex items-center space-x-2">
29
- <RadioGroupItem value="option-3" id="option-3" />
30
- <Label htmlFor="option-3">Option 3</Label>
31
- </div>
32
- </RadioGroup>
33
- );
34
- };
35
-
36
- export const Default = () => (
37
- <RadioGroup defaultValue="comfortable">
38
- <div className="flex items-center space-x-2">
39
- <RadioGroupItem value="default" id="r1" />
40
- <Label htmlFor="r1">Default</Label>
41
- </div>
42
- <div className="flex items-center space-x-2">
43
- <RadioGroupItem value="comfortable" id="r2" />
44
- <Label htmlFor="r2">Comfortable</Label>
45
- </div>
46
- <div className="flex items-center space-x-2">
47
- <RadioGroupItem value="compact" id="r3" />
48
- <Label htmlFor="r3">Compact</Label>
49
- </div>
50
- </RadioGroup>
51
- );
52
-
53
- export const Horizontal = () => (
54
- <RadioGroup defaultValue="card" className="flex gap-4">
55
- <div className="flex items-center space-x-2">
56
- <RadioGroupItem value="card" id="card" />
57
- <Label htmlFor="card">Card</Label>
58
- </div>
59
- <div className="flex items-center space-x-2">
60
- <RadioGroupItem value="paypal" id="paypal" />
61
- <Label htmlFor="paypal">PayPal</Label>
62
- </div>
63
- <div className="flex items-center space-x-2">
64
- <RadioGroupItem value="apple" id="apple" />
65
- <Label htmlFor="apple">Apple Pay</Label>
66
- </div>
67
- </RadioGroup>
68
- );
69
-
70
- export const Disabled = () => (
71
- <RadioGroup defaultValue="option-1" disabled>
72
- <div className="flex items-center space-x-2">
73
- <RadioGroupItem value="option-1" id="d1" />
74
- <Label htmlFor="d1">Option 1</Label>
75
- </div>
76
- <div className="flex items-center space-x-2">
77
- <RadioGroupItem value="option-2" id="d2" />
78
- <Label htmlFor="d2">Option 2</Label>
79
- </div>
80
- </RadioGroup>
81
- );
82
-
83
- export const WithDescriptions = () => (
84
- <RadioGroup defaultValue="startup" className="space-y-4">
85
- <div className="flex items-start space-x-3">
86
- <RadioGroupItem value="startup" id="startup" className="mt-1" />
87
- <div>
88
- <Label htmlFor="startup" className="font-medium">Startup</Label>
89
- <p className="text-sm text-muted-foreground">
90
- Perfect for small teams and startups.
91
- </p>
92
- </div>
93
- </div>
94
- <div className="flex items-start space-x-3">
95
- <RadioGroupItem value="business" id="business" className="mt-1" />
96
- <div>
97
- <Label htmlFor="business" className="font-medium">Business</Label>
98
- <p className="text-sm text-muted-foreground">
99
- For growing businesses with advanced needs.
100
- </p>
101
- </div>
102
- </div>
103
- <div className="flex items-start space-x-3">
104
- <RadioGroupItem value="enterprise" id="enterprise" className="mt-1" />
105
- <div>
106
- <Label htmlFor="enterprise" className="font-medium">Enterprise</Label>
107
- <p className="text-sm text-muted-foreground">
108
- Custom solutions for large organizations.
109
- </p>
110
- </div>
111
- </div>
112
- </RadioGroup>
113
- );
@@ -1,134 +0,0 @@
1
- import { useState } from 'react';
2
- import { defineStory, useBoolean, useNumber } from '@djangocfg/playground';
3
- import { Slider } from '.';
4
- import { Label } from '../../forms/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
- );
114
-
115
- export const Vertical = () => {
116
- const [value, setValue] = useState([70]);
117
-
118
- return (
119
- <div className="flex items-start gap-8">
120
- <div className="flex flex-col items-center gap-2">
121
- <span className="text-sm text-muted-foreground">{value[0]}%</span>
122
- <Slider
123
- orientation="vertical"
124
- value={value}
125
- onValueChange={setValue}
126
- max={100}
127
- step={5}
128
- className="h-32"
129
- />
130
- <Label>Volume</Label>
131
- </div>
132
- </div>
133
- );
134
- };