aural-ui 2.1.4 → 2.1.6

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.
@@ -30,6 +30,24 @@ const meta: Meta<typeof Switch> = {
30
30
  control: { type: "boolean" },
31
31
  description: "Whether the switch is disabled or not",
32
32
  },
33
+ size: {
34
+ control: { type: "select" },
35
+ options: ["sm", "md", "lg"],
36
+ description: "Size variant of the switch",
37
+ defaultValue: "md",
38
+ },
39
+ onIcon: {
40
+ control: { type: "text" },
41
+ description: "Custom icon to display when switch is ON",
42
+ },
43
+ offIcon: {
44
+ control: { type: "text" },
45
+ description: "Custom icon to display when switch is OFF",
46
+ },
47
+ classNames: {
48
+ control: { type: "object" },
49
+ description: "Custom classNames for different parts of the switch",
50
+ },
33
51
  },
34
52
  }
35
53
 
@@ -61,6 +79,37 @@ export const DisabledAndChecked: Story = {
61
79
  },
62
80
  }
63
81
 
82
+ export const SizeVariants: Story = {
83
+ render: () => (
84
+ <div className="flex flex-col items-center space-y-4">
85
+ <div className="flex items-center space-x-4">
86
+ <Switch size="sm" checked={true} />
87
+ <span className="text-sm text-gray-400">Small (sm)</span>
88
+ </div>
89
+ <div className="flex items-center space-x-4">
90
+ <Switch size="md" checked={true} />
91
+ <span className="text-sm text-gray-400">Medium (md)</span>
92
+ </div>
93
+ <div className="flex items-center space-x-4">
94
+ <Switch size="lg" checked={true} />
95
+ <span className="text-sm text-gray-400">Large (lg)</span>
96
+ </div>
97
+ </div>
98
+ ),
99
+ }
100
+
101
+ export const WithCustomClassNames: Story = {
102
+ args: {
103
+ checked: true,
104
+ classNames: {
105
+ root: "border-2 border-blue-500",
106
+ onIcon: "text-green-600 font-bold",
107
+ offIcon: "text-gray-400",
108
+ thumb: "bg-blue-500 shadow-xl",
109
+ },
110
+ },
111
+ }
112
+
64
113
  export const WithLabel: Story = {
65
114
  render: () => (
66
115
  <div className="flex items-center space-x-2">
@@ -108,3 +157,57 @@ export const CheckedWithIcons: Story = {
108
157
  offIcon: <CrossIcon />,
109
158
  },
110
159
  }
160
+
161
+ export const AllVariants: Story = {
162
+ render: () => (
163
+ <div className="grid grid-cols-2 gap-6">
164
+ <div className="space-y-4">
165
+ <h3 className="text-lg font-semibold">Size Variants</h3>
166
+ <div className="space-y-3">
167
+ <div className="flex items-center justify-between">
168
+ <span>Small</span>
169
+ <Switch size="sm" checked={true} />
170
+ </div>
171
+ <div className="flex items-center justify-between">
172
+ <span>Medium</span>
173
+ <Switch size="md" checked={true} />
174
+ </div>
175
+ <div className="flex items-center justify-between">
176
+ <span>Large</span>
177
+ <Switch size="lg" checked={true} />
178
+ </div>
179
+ </div>
180
+ </div>
181
+
182
+ <div className="space-y-4">
183
+ <h3 className="text-lg font-semibold">With Custom Styling</h3>
184
+ <div className="space-y-3">
185
+ <div className="flex items-center justify-between">
186
+ <span>Custom Colors</span>
187
+ <Switch
188
+ size="md"
189
+ checked={true}
190
+ classNames={{
191
+ root: "border-2 border-purple-500",
192
+ thumb: "bg-purple-500",
193
+ }}
194
+ />
195
+ </div>
196
+ <div className="flex items-center justify-between">
197
+ <span>With Icons</span>
198
+ <Switch
199
+ size="md"
200
+ checked={true}
201
+ onIcon={<TickIcon />}
202
+ offIcon={<CrossIcon />}
203
+ />
204
+ </div>
205
+ <div className="flex items-center justify-between">
206
+ <span>Disabled</span>
207
+ <Switch size="md" checked={true} disabled />
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </div>
212
+ ),
213
+ }
@@ -1,57 +1,129 @@
1
1
  import * as React from "react"
2
2
  import { cn } from "@lib/utils"
3
3
  import * as SwitchPrimitives from "@radix-ui/react-switch"
4
+ import clsx from "clsx"
5
+
6
+ type SwitchSize = "sm" | "md" | "lg"
7
+
8
+ type SwitchClassNames = {
9
+ root?: string
10
+ onIcon?: string
11
+ offIcon?: string
12
+ thumb?: string
13
+ }
4
14
 
5
15
  type SwitchWithIconsProps = React.ComponentPropsWithoutRef<
6
16
  typeof SwitchPrimitives.Root
7
17
  > & {
8
18
  offIcon?: React.ReactNode
9
19
  onIcon?: React.ReactNode
20
+ size?: SwitchSize
21
+ classNames?: SwitchClassNames
22
+ }
23
+
24
+ const switchVariants = {
25
+ size: {
26
+ sm: {
27
+ root: "h-6 w-12",
28
+ thumb:
29
+ "size-4 data-[state=checked]:translate-x-6.5 data-[state=unchecked]:translate-x-1",
30
+ onIcon: "left-1 text-fm-xs",
31
+ offIcon: "right-[5px] text-fm-xs",
32
+ },
33
+ md: {
34
+ root: "h-8 w-14",
35
+ thumb:
36
+ "size-6 data-[state=checked]:translate-x-7 data-[state=unchecked]:translate-x-1",
37
+ onIcon: "left-2 text-fm-sm",
38
+ offIcon: "right-1.5 text-fm-sm",
39
+ },
40
+ lg: {
41
+ root: "h-10 w-18",
42
+ thumb:
43
+ "size-8 data-[state=checked]:translate-x-9 data-[state=unchecked]:translate-x-1",
44
+ onIcon: "left-2.5 text-fm-base",
45
+ offIcon: "right-2 text-fm-base",
46
+ },
47
+ },
10
48
  }
11
49
 
12
50
  const Switch = React.forwardRef<
13
51
  React.ElementRef<typeof SwitchPrimitives.Root>,
14
52
  SwitchWithIconsProps
15
- >(({ className, onIcon, offIcon, checked, disabled, ...props }, ref) => (
16
- <SwitchPrimitives.Root
17
- ref={ref}
18
- checked={checked}
19
- disabled={disabled}
20
- className={cn(
21
- "data-[state=checked]:not-[:disabled]:border-fm-divider-positive data-[state=checked]:not-[:disabled]:bg-fm-green-50",
22
- "data-[state=unchecked]:not-[:disabled]:border-fm-divider-primary data-[state=unchecked]:not-[:disabled]:bg-fm-surface-primary",
23
- "data-[state=unchecked]:disabled:border-fm-divider-tertiary data-[state=unchecked]:disabled:bg-fm-surface-secondary",
24
- "data-[state=checked]:disabled:border-fm-green-100 data-[state=checked]:disabled:bg-fm-green-50",
25
- "focus-visible:ring-fm-primary focus-visible:ring-offset-fm-green-50",
26
- "hover:bg-fm-surface-secondary data-[state=unchecked]:not-[:disabled]:hover:bg-fm-surface-secondary",
27
- "data-[state=unchecked]:not-[:disabled]:hover:border-fm-divider-primary",
28
- "relative h-8 w-14 rounded-full border border-solid transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed",
29
- className
30
- )}
31
- {...props}
32
- >
33
- <span
34
- className={cn(
35
- "font-fm-brand text-fm-positive absolute top-1/2 left-2 -translate-y-1/2 [font-size:var(--text-fm-sm)]",
36
- disabled && "text-fm-positive-tert"
37
- )}
38
- data-state={checked ? "checked" : "unchecked"}
39
- data-disabled={disabled || undefined}
40
- >
41
- {onIcon ?? "ON"}
42
- </span>
43
-
44
- <span
45
- className="font-fm-brand text-fm-tertiary absolute top-1/2 right-1.5 -translate-y-1/2 [font-size:var(--text-fm-sm)]"
46
- data-state={checked ? "checked" : "unchecked"}
47
- data-disabled={disabled || undefined}
48
- >
49
- {offIcon ?? "OFF"}
50
- </span>
51
-
52
- <SwitchPrimitives.Thumb className="bg-fm-icon-active data-[disabled]:bg-fm-icon-inactive pointer-events-none z-10 block size-6 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-7 data-[state=unchecked]:translate-x-1" />
53
- </SwitchPrimitives.Root>
54
- ))
53
+ >(
54
+ (
55
+ {
56
+ className,
57
+ onIcon,
58
+ offIcon,
59
+ checked,
60
+ disabled,
61
+ size = "md",
62
+ classNames,
63
+ ...props
64
+ },
65
+ ref
66
+ ) => {
67
+ const sizeConfig = switchVariants.size[size]
68
+
69
+ return (
70
+ <SwitchPrimitives.Root
71
+ ref={ref}
72
+ checked={checked}
73
+ disabled={disabled}
74
+ className={cn(
75
+ "data-[state=checked]:not-[:disabled]:border-fm-divider-positive data-[state=checked]:not-[:disabled]:bg-fm-green-50",
76
+ "data-[state=unchecked]:not-[:disabled]:border-fm-divider-primary data-[state=unchecked]:not-[:disabled]:bg-fm-surface-primary",
77
+ "data-[state=unchecked]:disabled:border-fm-divider-tertiary data-[state=unchecked]:disabled:bg-fm-surface-secondary",
78
+ "data-[state=checked]:disabled:border-fm-green-100 data-[state=checked]:disabled:bg-fm-green-50",
79
+ "focus-visible:ring-fm-primary focus-visible:ring-offset-fm-green-50",
80
+ "hover:bg-fm-surface-secondary data-[state=unchecked]:not-[:disabled]:hover:bg-fm-surface-secondary",
81
+ "data-[state=unchecked]:not-[:disabled]:hover:border-fm-divider-primary",
82
+ "relative rounded-full border border-solid transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed",
83
+ sizeConfig.root,
84
+ classNames?.root,
85
+ className
86
+ )}
87
+ {...props}
88
+ >
89
+ <span
90
+ className={clsx(
91
+ "font-fm-brand text-fm-positive absolute top-1/2 -translate-y-1/2",
92
+ {
93
+ "text-fm-positive-tert": disabled,
94
+ },
95
+ sizeConfig.onIcon,
96
+ classNames?.onIcon
97
+ )}
98
+ data-state={checked ? "checked" : "unchecked"}
99
+ data-disabled={disabled || undefined}
100
+ >
101
+ {onIcon ?? "ON"}
102
+ </span>
103
+
104
+ <span
105
+ className={clsx(
106
+ "font-fm-brand text-fm-tertiary absolute top-1/2 -translate-y-1/2",
107
+ sizeConfig.offIcon,
108
+ classNames?.offIcon
109
+ )}
110
+ data-state={checked ? "checked" : "unchecked"}
111
+ data-disabled={disabled || undefined}
112
+ >
113
+ {offIcon ?? "OFF"}
114
+ </span>
115
+
116
+ <SwitchPrimitives.Thumb
117
+ className={cn(
118
+ "bg-fm-icon-active data-[disabled]:bg-fm-icon-inactive pointer-events-none z-10 block rounded-full shadow-lg ring-0 transition-transform",
119
+ sizeConfig.thumb,
120
+ classNames?.thumb
121
+ )}
122
+ />
123
+ </SwitchPrimitives.Root>
124
+ )
125
+ }
126
+ )
55
127
  Switch.displayName = SwitchPrimitives.Root.displayName
56
128
 
57
- export { Switch }
129
+ export { Switch, type SwitchSize, type SwitchClassNames }