@adamosuiteservices/ui 2.11.16 → 2.11.18
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/dist/accordion-rounded.cjs +1 -1
- package/dist/accordion-rounded.js +1 -1
- package/dist/badge.cjs +3 -3
- package/dist/badge.js +2 -2
- package/dist/breadcrumb.cjs +5 -5
- package/dist/breadcrumb.js +16 -16
- package/dist/components/ui/date-picker-selector/date-picker-selector.d.ts +2 -2
- package/dist/components/ui/sheet/sheet.d.ts +2 -1
- package/dist/date-picker-selector.cjs +1 -1
- package/dist/date-picker-selector.js +29 -30
- package/dist/dialog.cjs +1 -1
- package/dist/dialog.js +1 -1
- package/dist/select.cjs +2 -2
- package/dist/select.js +2 -2
- package/dist/{sheet-DVT_djHX.cjs → sheet-CvcCaGSl.cjs} +11 -11
- package/dist/{sheet-CPf9Guon.js → sheet-IRIc3TJ1.js} +33 -19
- package/dist/sheet.cjs +1 -1
- package/dist/sheet.js +7 -6
- package/dist/sidebar.cjs +1 -1
- package/dist/sidebar.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/tabs-underline.cjs +3 -3
- package/dist/tabs-underline.js +13 -13
- package/dist/tabs.cjs +5 -4
- package/dist/tabs.js +3 -2
- package/dist/themes.css +1 -1
- package/docs/AI-GUIDE.md +321 -321
- package/docs/components/layout/sidebar.md +399 -399
- package/docs/components/layout/toaster.md +436 -436
- package/docs/components/ui/accordion-rounded.md +584 -584
- package/docs/components/ui/accordion.md +269 -269
- package/docs/components/ui/badge.md +2 -1
- package/docs/components/ui/button-group.md +984 -984
- package/docs/components/ui/button.md +1137 -1137
- package/docs/components/ui/calendar.md +1159 -1159
- package/docs/components/ui/card.md +1455 -1455
- package/docs/components/ui/checkbox.md +292 -292
- package/docs/components/ui/collapsible.md +323 -323
- package/docs/components/ui/command.md +454 -454
- package/docs/components/ui/context-menu.md +540 -540
- package/docs/components/ui/date-picker-selector.md +0 -2
- package/docs/components/ui/dialog.md +628 -628
- package/docs/components/ui/dropdown-menu.md +709 -709
- package/docs/components/ui/field.md +706 -706
- package/docs/components/ui/hover-card.md +446 -446
- package/docs/components/ui/input.md +362 -362
- package/docs/components/ui/kbd.md +434 -434
- package/docs/components/ui/label.md +359 -359
- package/docs/components/ui/pagination.md +650 -650
- package/docs/components/ui/popover.md +536 -536
- package/docs/components/ui/progress.md +182 -182
- package/docs/components/ui/radio-group.md +311 -311
- package/docs/components/ui/select.md +352 -352
- package/docs/components/ui/separator.md +214 -214
- package/docs/components/ui/sheet.md +174 -142
- package/docs/components/ui/skeleton.md +140 -140
- package/docs/components/ui/slider.md +341 -341
- package/docs/components/ui/spinner.md +170 -170
- package/docs/components/ui/switch.md +408 -408
- package/docs/components/ui/tabs-underline.md +106 -106
- package/docs/components/ui/tabs.md +122 -122
- package/docs/components/ui/textarea.md +243 -243
- package/docs/components/ui/toggle.md +237 -237
- package/docs/components/ui/tooltip.md +317 -317
- package/docs/components/ui/typography.md +280 -280
- package/package.json +1 -1
|
@@ -1,408 +1,408 @@
|
|
|
1
|
-
# Switch
|
|
2
|
-
|
|
3
|
-
Toggle binario on/off. Basado en Radix UI con animación de thumb.
|
|
4
|
-
|
|
5
|
-
## Descripción
|
|
6
|
-
|
|
7
|
-
El componente `Switch` es un control de toggle que representa un estado booleano (on/off).
|
|
8
|
-
|
|
9
|
-
## Importación
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
import { Switch } from "@adamosuiteservices/ui/switch";
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Anatomía
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
<Switch />
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
**Componentes**: 1 (Switch) con thumb interno
|
|
22
|
-
|
|
23
|
-
## Props
|
|
24
|
-
|
|
25
|
-
| Prop | Tipo | Descripción |
|
|
26
|
-
| ----------------- | ---------------------------- | ----------------------------- |
|
|
27
|
-
| `defaultChecked` | `boolean` | Estado inicial (uncontrolled) |
|
|
28
|
-
| `checked` | `boolean` | Estado controlado |
|
|
29
|
-
| `onCheckedChange` | `(checked: boolean) => void` | Callback al cambiar |
|
|
30
|
-
| `disabled` | `boolean` | Deshabilita el switch |
|
|
31
|
-
| `required` | `boolean` | Campo requerido |
|
|
32
|
-
| `name` | `string` | Nombre (formularios) |
|
|
33
|
-
| `value` | `string` | Valor (formularios) |
|
|
34
|
-
| `id` | `string` | ID para asociar con Label |
|
|
35
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
36
|
-
|
|
37
|
-
**Nota**: Acepta todas las props de Radix UI Switch.Root
|
|
38
|
-
|
|
39
|
-
## Patrones de Uso
|
|
40
|
-
|
|
41
|
-
### Básico
|
|
42
|
-
|
|
43
|
-
```tsx
|
|
44
|
-
import { Switch } from "@adamosuiteservices/ui/switch";
|
|
45
|
-
|
|
46
|
-
<Switch />;
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### Con Label
|
|
50
|
-
|
|
51
|
-
```tsx
|
|
52
|
-
import { Label } from "@adamosuiteservices/ui/label";
|
|
53
|
-
|
|
54
|
-
<div className="flex items-center space-x-2">
|
|
55
|
-
<Switch id="airplane-mode" />
|
|
56
|
-
<Label htmlFor="airplane-mode">Airplane Mode</Label>
|
|
57
|
-
</div>;
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### Controlado
|
|
61
|
-
|
|
62
|
-
```tsx
|
|
63
|
-
import { useState } from "react";
|
|
64
|
-
|
|
65
|
-
function App() {
|
|
66
|
-
const [isChecked, setIsChecked] = useState(false);
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
<div className="flex items-center space-x-2">
|
|
70
|
-
<Switch
|
|
71
|
-
id="controlled-switch"
|
|
72
|
-
checked={isChecked}
|
|
73
|
-
onCheckedChange={setIsChecked}
|
|
74
|
-
/>
|
|
75
|
-
<Label htmlFor="controlled-switch">
|
|
76
|
-
Notifications {isChecked ? "enabled" : "disabled"}
|
|
77
|
-
</Label>
|
|
78
|
-
</div>
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Con Iconos y Badges
|
|
84
|
-
|
|
85
|
-
```tsx
|
|
86
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
87
|
-
import { Badge } from "@adamosuiteservices/ui/badge";
|
|
88
|
-
|
|
89
|
-
function Settings() {
|
|
90
|
-
const [settings, setSettings] = useState({
|
|
91
|
-
notifications: true,
|
|
92
|
-
darkMode: false,
|
|
93
|
-
wifi: true,
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<div className="space-y-4">
|
|
98
|
-
<div className="flex items-center space-x-3">
|
|
99
|
-
<Icon
|
|
100
|
-
symbol="notifications"
|
|
101
|
-
className="text-lg text-muted-foreground"
|
|
102
|
-
/>
|
|
103
|
-
<Switch
|
|
104
|
-
checked={settings.notifications}
|
|
105
|
-
onCheckedChange={(checked) =>
|
|
106
|
-
setSettings((prev) => ({ ...prev, notifications: checked }))
|
|
107
|
-
}
|
|
108
|
-
/>
|
|
109
|
-
<Label>Notifications</Label>
|
|
110
|
-
<Badge variant={settings.notifications ? "default" : "secondary"}>
|
|
111
|
-
{settings.notifications ? "On" : "Off"}
|
|
112
|
-
</Badge>
|
|
113
|
-
</div>
|
|
114
|
-
|
|
115
|
-
<div className="flex items-center space-x-3">
|
|
116
|
-
<Icon symbol="dark_mode" className="text-lg text-muted-foreground" />
|
|
117
|
-
<Switch
|
|
118
|
-
checked={settings.darkMode}
|
|
119
|
-
onCheckedChange={(checked) =>
|
|
120
|
-
setSettings((prev) => ({ ...prev, darkMode: checked }))
|
|
121
|
-
}
|
|
122
|
-
/>
|
|
123
|
-
<Label>Dark Mode</Label>
|
|
124
|
-
<Badge variant={settings.darkMode ? "default" : "secondary"}>
|
|
125
|
-
{settings.darkMode ? "On" : "Off"}
|
|
126
|
-
</Badge>
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Device Controls
|
|
134
|
-
|
|
135
|
-
```tsx
|
|
136
|
-
import {
|
|
137
|
-
Card,
|
|
138
|
-
CardContent,
|
|
139
|
-
CardDescription,
|
|
140
|
-
CardHeader,
|
|
141
|
-
CardTitle,
|
|
142
|
-
} from "@adamosuiteservices/ui/card";
|
|
143
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
144
|
-
|
|
145
|
-
function ControlCenter() {
|
|
146
|
-
const [deviceSettings, setDeviceSettings] = useState({
|
|
147
|
-
airplaneMode: false,
|
|
148
|
-
wifi: true,
|
|
149
|
-
bluetooth: false,
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const updateSetting = (key: keyof typeof deviceSettings) => {
|
|
153
|
-
setDeviceSettings((prev) => ({ ...prev, [key]: !prev[key] }));
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
return (
|
|
157
|
-
<Card className="w-full max-w-sm">
|
|
158
|
-
<CardHeader>
|
|
159
|
-
<CardTitle>Control Center</CardTitle>
|
|
160
|
-
<CardDescription>Quick access to device settings</CardDescription>
|
|
161
|
-
</CardHeader>
|
|
162
|
-
<CardContent className="space-y-4">
|
|
163
|
-
<div className="grid grid-cols-2 gap-4">
|
|
164
|
-
<div className="flex flex-col items-center space-y-2 p-3 border rounded-lg">
|
|
165
|
-
<Icon symbol="flight" className="text-2xl text-muted-foreground" />
|
|
166
|
-
<span className="text-sm font-medium">Airplane</span>
|
|
167
|
-
<Switch
|
|
168
|
-
checked={deviceSettings.airplaneMode}
|
|
169
|
-
onCheckedChange={() => updateSetting("airplaneMode")}
|
|
170
|
-
className="scale-75"
|
|
171
|
-
/>
|
|
172
|
-
</div>
|
|
173
|
-
|
|
174
|
-
<div className="flex flex-col items-center space-y-2 p-3 border rounded-lg">
|
|
175
|
-
<Icon symbol="wifi" className="text-2xl text-muted-foreground" />
|
|
176
|
-
<span className="text-sm font-medium">Wi-Fi</span>
|
|
177
|
-
<Switch
|
|
178
|
-
checked={deviceSettings.wifi}
|
|
179
|
-
onCheckedChange={() => updateSetting("wifi")}
|
|
180
|
-
className="scale-75"
|
|
181
|
-
/>
|
|
182
|
-
</div>
|
|
183
|
-
|
|
184
|
-
<div className="flex flex-col items-center space-y-2 p-3 border rounded-lg">
|
|
185
|
-
<Icon
|
|
186
|
-
symbol="bluetooth"
|
|
187
|
-
className="text-2xl text-muted-foreground"
|
|
188
|
-
/>
|
|
189
|
-
<span className="text-sm font-medium">Bluetooth</span>
|
|
190
|
-
<Switch
|
|
191
|
-
checked={deviceSettings.bluetooth}
|
|
192
|
-
onCheckedChange={() => updateSetting("bluetooth")}
|
|
193
|
-
className="scale-75"
|
|
194
|
-
/>
|
|
195
|
-
</div>
|
|
196
|
-
</div>
|
|
197
|
-
</CardContent>
|
|
198
|
-
</Card>
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### Privacy Settings
|
|
204
|
-
|
|
205
|
-
```tsx
|
|
206
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
207
|
-
import { Button } from "@adamosuiteservices/ui/button";
|
|
208
|
-
|
|
209
|
-
function PrivacySettings() {
|
|
210
|
-
const [privacySettings, setPrivacySettings] = useState({
|
|
211
|
-
locationServices: true,
|
|
212
|
-
analyticsData: false,
|
|
213
|
-
crashReports: true,
|
|
214
|
-
personalizedAds: false,
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
return (
|
|
218
|
-
<Card className="w-full max-w-lg">
|
|
219
|
-
<CardHeader>
|
|
220
|
-
<CardTitle className="flex items-center space-x-2">
|
|
221
|
-
<Icon symbol="shield" className="text-xl" />
|
|
222
|
-
<span>Privacy & Security</span>
|
|
223
|
-
</CardTitle>
|
|
224
|
-
<CardDescription>
|
|
225
|
-
Control how your data is collected and used
|
|
226
|
-
</CardDescription>
|
|
227
|
-
</CardHeader>
|
|
228
|
-
<CardContent className="space-y-6">
|
|
229
|
-
<div className="space-y-4">
|
|
230
|
-
<div className="flex items-start justify-between space-x-4">
|
|
231
|
-
<div className="flex-1">
|
|
232
|
-
<Label className="text-sm font-medium">Location Services</Label>
|
|
233
|
-
<p className="text-xs text-muted-foreground mt-1">
|
|
234
|
-
Allow apps to access your location for personalized experiences
|
|
235
|
-
</p>
|
|
236
|
-
</div>
|
|
237
|
-
<Switch
|
|
238
|
-
checked={privacySettings.locationServices}
|
|
239
|
-
onCheckedChange={(checked) =>
|
|
240
|
-
setPrivacySettings((prev) => ({
|
|
241
|
-
...prev,
|
|
242
|
-
locationServices: checked,
|
|
243
|
-
}))
|
|
244
|
-
}
|
|
245
|
-
/>
|
|
246
|
-
</div>
|
|
247
|
-
|
|
248
|
-
<div className="flex items-start justify-between space-x-4">
|
|
249
|
-
<div className="flex-1">
|
|
250
|
-
<Label className="text-sm font-medium">
|
|
251
|
-
Analytics & Diagnostics
|
|
252
|
-
</Label>
|
|
253
|
-
<p className="text-xs text-muted-foreground mt-1">
|
|
254
|
-
Share analytics data to help improve our products
|
|
255
|
-
</p>
|
|
256
|
-
</div>
|
|
257
|
-
<Switch
|
|
258
|
-
checked={privacySettings.analyticsData}
|
|
259
|
-
onCheckedChange={(checked) =>
|
|
260
|
-
setPrivacySettings((prev) => ({
|
|
261
|
-
...prev,
|
|
262
|
-
analyticsData: checked,
|
|
263
|
-
}))
|
|
264
|
-
}
|
|
265
|
-
/>
|
|
266
|
-
</div>
|
|
267
|
-
</div>
|
|
268
|
-
|
|
269
|
-
<div className="flex justify-end space-x-2 pt-4 border-t">
|
|
270
|
-
<Button variant="outline" size="sm">
|
|
271
|
-
Reset to Defaults
|
|
272
|
-
</Button>
|
|
273
|
-
<Button size="sm">Save Changes</Button>
|
|
274
|
-
</div>
|
|
275
|
-
</CardContent>
|
|
276
|
-
</Card>
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
### Feature Toggles
|
|
282
|
-
|
|
283
|
-
```tsx
|
|
284
|
-
function FeatureToggles() {
|
|
285
|
-
const [features, setFeatures] = useState({
|
|
286
|
-
newDashboard: false,
|
|
287
|
-
betaFeatures: false,
|
|
288
|
-
experimentalUI: false,
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
const updateFeature = (key: keyof typeof features) => {
|
|
292
|
-
setFeatures((prev) => ({ ...prev, [key]: !prev[key] }));
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
return (
|
|
296
|
-
<Card className="w-full max-w-lg">
|
|
297
|
-
<CardHeader>
|
|
298
|
-
<CardTitle>Feature Toggles</CardTitle>
|
|
299
|
-
<CardDescription>
|
|
300
|
-
Enable or disable experimental features
|
|
301
|
-
</CardDescription>
|
|
302
|
-
</CardHeader>
|
|
303
|
-
<CardContent className="space-y-4">
|
|
304
|
-
<div className="flex items-start justify-between space-x-4 p-3 border rounded-lg">
|
|
305
|
-
<div className="flex-1 space-y-1">
|
|
306
|
-
<div className="flex items-center space-x-2">
|
|
307
|
-
<Label className="text-sm font-medium">New Dashboard</Label>
|
|
308
|
-
<Badge variant="default" className="text-xs">
|
|
309
|
-
New
|
|
310
|
-
</Badge>
|
|
311
|
-
</div>
|
|
312
|
-
<p className="text-xs text-muted-foreground">
|
|
313
|
-
Try our redesigned dashboard interface
|
|
314
|
-
</p>
|
|
315
|
-
</div>
|
|
316
|
-
<Switch
|
|
317
|
-
checked={features.newDashboard}
|
|
318
|
-
onCheckedChange={() => updateFeature("newDashboard")}
|
|
319
|
-
/>
|
|
320
|
-
</div>
|
|
321
|
-
|
|
322
|
-
<div className="flex items-start justify-between space-x-4 p-3 border rounded-lg">
|
|
323
|
-
<div className="flex-1 space-y-1">
|
|
324
|
-
<div className="flex items-center space-x-2">
|
|
325
|
-
<Label className="text-sm font-medium">Beta Features</Label>
|
|
326
|
-
<Badge variant="secondary" className="text-xs">
|
|
327
|
-
Beta
|
|
328
|
-
</Badge>
|
|
329
|
-
</div>
|
|
330
|
-
<p className="text-xs text-muted-foreground">
|
|
331
|
-
Access features currently in beta testing
|
|
332
|
-
</p>
|
|
333
|
-
</div>
|
|
334
|
-
<Switch
|
|
335
|
-
checked={features.betaFeatures}
|
|
336
|
-
onCheckedChange={() => updateFeature("betaFeatures")}
|
|
337
|
-
/>
|
|
338
|
-
</div>
|
|
339
|
-
</CardContent>
|
|
340
|
-
</Card>
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
### Deshabilitado
|
|
346
|
-
|
|
347
|
-
```tsx
|
|
348
|
-
<div className="space-y-4">
|
|
349
|
-
<div className="flex items-center space-x-2">
|
|
350
|
-
<Switch disabled />
|
|
351
|
-
<Label className="text-muted-foreground">Disabled (off)</Label>
|
|
352
|
-
</div>
|
|
353
|
-
<div className="flex items-center space-x-2">
|
|
354
|
-
<Switch disabled checked />
|
|
355
|
-
<Label className="text-muted-foreground">Disabled (on)</Label>
|
|
356
|
-
</div>
|
|
357
|
-
</div>
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
## Casos de Uso
|
|
361
|
-
|
|
362
|
-
**Settings**: On/off toggles para configuración
|
|
363
|
-
**Feature flags**: Activar/desactivar features
|
|
364
|
-
**Notifications**: Habilitar/deshabilitar notificaciones
|
|
365
|
-
**Privacy**: Controles de privacidad y permisos
|
|
366
|
-
**Device controls**: Wi-Fi, Bluetooth, Airplane mode
|
|
367
|
-
**Filters**: Mostrar/ocultar contenido
|
|
368
|
-
|
|
369
|
-
## Estilos Base
|
|
370
|
-
|
|
371
|
-
- **Size**: `h-5 w-8`
|
|
372
|
-
- **Checked bg**: `bg-primary`
|
|
373
|
-
- **Unchecked bg**: `bg-input` (dark: `bg-input/80`)
|
|
374
|
-
- **Thumb**: `size-4` con `bg-background`
|
|
375
|
-
- **Thumb checked**: `translate-x-[calc(100%-2px)]`
|
|
376
|
-
- **Thumb unchecked**: `translate-x-0`
|
|
377
|
-
- **Focus**: `ring-ring/50` con `ring-[3px]`
|
|
378
|
-
- **Transition**: `transition-all` en thumb y background
|
|
379
|
-
|
|
380
|
-
## Accesibilidad
|
|
381
|
-
|
|
382
|
-
- ✅ **Role**: `role="switch"` con `aria-checked`
|
|
383
|
-
- ✅ **Keyboard**: Space/Enter para toggle
|
|
384
|
-
- ✅ **Focus**: Focus ring visible
|
|
385
|
-
- ✅ **Label**: Asociar con `htmlFor` e `id`
|
|
386
|
-
- ✅ **State**: Screen readers anuncian checked/unchecked
|
|
387
|
-
|
|
388
|
-
## Notas de Implementación
|
|
389
|
-
|
|
390
|
-
- **Radix UI**: Basado en `@radix-ui/react-switch`
|
|
391
|
-
- **Peer class**: Usa `peer` para estilos relacionados con Label
|
|
392
|
-
- **Data states**: `data-state="checked|unchecked"` para estilos
|
|
393
|
-
- **Controlled**: Usa `checked` + `onCheckedChange`
|
|
394
|
-
- **Uncontrolled**: Usa `defaultChecked`
|
|
395
|
-
- **Dark mode**: Thumb color cambia automáticamente
|
|
396
|
-
|
|
397
|
-
## Troubleshooting
|
|
398
|
-
|
|
399
|
-
**No cambia estado**: En modo controlado usa `checked` + `onCheckedChange`, no `defaultChecked`
|
|
400
|
-
**Label no clickeable**: Asegura `htmlFor` en Label coincida con `id` del Switch
|
|
401
|
-
**Thumb no anima**: Verifica que estilos de `transition-transform` no estén sobrescritos
|
|
402
|
-
**Color incorrecto**: Switch usa `bg-primary` checked, `bg-input` unchecked
|
|
403
|
-
**Disabled no funciona**: Prop `disabled` deshabilita interacción
|
|
404
|
-
|
|
405
|
-
## Referencias
|
|
406
|
-
|
|
407
|
-
- **Radix UI Switch**: <https://www.radix-ui.com/primitives/docs/components/switch>
|
|
408
|
-
- **shadcn/ui Switch**: <https://ui.shadcn.com/docs/components/switch>
|
|
1
|
+
# Switch
|
|
2
|
+
|
|
3
|
+
Toggle binario on/off. Basado en Radix UI con animación de thumb.
|
|
4
|
+
|
|
5
|
+
## Descripción
|
|
6
|
+
|
|
7
|
+
El componente `Switch` es un control de toggle que representa un estado booleano (on/off).
|
|
8
|
+
|
|
9
|
+
## Importación
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { Switch } from "@adamosuiteservices/ui/switch";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Anatomía
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
<Switch />
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Componentes**: 1 (Switch) con thumb interno
|
|
22
|
+
|
|
23
|
+
## Props
|
|
24
|
+
|
|
25
|
+
| Prop | Tipo | Descripción |
|
|
26
|
+
| ----------------- | ---------------------------- | ----------------------------- |
|
|
27
|
+
| `defaultChecked` | `boolean` | Estado inicial (uncontrolled) |
|
|
28
|
+
| `checked` | `boolean` | Estado controlado |
|
|
29
|
+
| `onCheckedChange` | `(checked: boolean) => void` | Callback al cambiar |
|
|
30
|
+
| `disabled` | `boolean` | Deshabilita el switch |
|
|
31
|
+
| `required` | `boolean` | Campo requerido |
|
|
32
|
+
| `name` | `string` | Nombre (formularios) |
|
|
33
|
+
| `value` | `string` | Valor (formularios) |
|
|
34
|
+
| `id` | `string` | ID para asociar con Label |
|
|
35
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
36
|
+
|
|
37
|
+
**Nota**: Acepta todas las props de Radix UI Switch.Root
|
|
38
|
+
|
|
39
|
+
## Patrones de Uso
|
|
40
|
+
|
|
41
|
+
### Básico
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { Switch } from "@adamosuiteservices/ui/switch";
|
|
45
|
+
|
|
46
|
+
<Switch />;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Con Label
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { Label } from "@adamosuiteservices/ui/label";
|
|
53
|
+
|
|
54
|
+
<div className="flex items-center space-x-2">
|
|
55
|
+
<Switch id="airplane-mode" />
|
|
56
|
+
<Label htmlFor="airplane-mode">Airplane Mode</Label>
|
|
57
|
+
</div>;
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Controlado
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { useState } from "react";
|
|
64
|
+
|
|
65
|
+
function App() {
|
|
66
|
+
const [isChecked, setIsChecked] = useState(false);
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<div className="flex items-center space-x-2">
|
|
70
|
+
<Switch
|
|
71
|
+
id="controlled-switch"
|
|
72
|
+
checked={isChecked}
|
|
73
|
+
onCheckedChange={setIsChecked}
|
|
74
|
+
/>
|
|
75
|
+
<Label htmlFor="controlled-switch">
|
|
76
|
+
Notifications {isChecked ? "enabled" : "disabled"}
|
|
77
|
+
</Label>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Con Iconos y Badges
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
87
|
+
import { Badge } from "@adamosuiteservices/ui/badge";
|
|
88
|
+
|
|
89
|
+
function Settings() {
|
|
90
|
+
const [settings, setSettings] = useState({
|
|
91
|
+
notifications: true,
|
|
92
|
+
darkMode: false,
|
|
93
|
+
wifi: true,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<div className="space-y-4">
|
|
98
|
+
<div className="flex items-center space-x-3">
|
|
99
|
+
<Icon
|
|
100
|
+
symbol="notifications"
|
|
101
|
+
className="text-lg text-muted-foreground"
|
|
102
|
+
/>
|
|
103
|
+
<Switch
|
|
104
|
+
checked={settings.notifications}
|
|
105
|
+
onCheckedChange={(checked) =>
|
|
106
|
+
setSettings((prev) => ({ ...prev, notifications: checked }))
|
|
107
|
+
}
|
|
108
|
+
/>
|
|
109
|
+
<Label>Notifications</Label>
|
|
110
|
+
<Badge variant={settings.notifications ? "default" : "secondary"}>
|
|
111
|
+
{settings.notifications ? "On" : "Off"}
|
|
112
|
+
</Badge>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<div className="flex items-center space-x-3">
|
|
116
|
+
<Icon symbol="dark_mode" className="text-lg text-muted-foreground" />
|
|
117
|
+
<Switch
|
|
118
|
+
checked={settings.darkMode}
|
|
119
|
+
onCheckedChange={(checked) =>
|
|
120
|
+
setSettings((prev) => ({ ...prev, darkMode: checked }))
|
|
121
|
+
}
|
|
122
|
+
/>
|
|
123
|
+
<Label>Dark Mode</Label>
|
|
124
|
+
<Badge variant={settings.darkMode ? "default" : "secondary"}>
|
|
125
|
+
{settings.darkMode ? "On" : "Off"}
|
|
126
|
+
</Badge>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Device Controls
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import {
|
|
137
|
+
Card,
|
|
138
|
+
CardContent,
|
|
139
|
+
CardDescription,
|
|
140
|
+
CardHeader,
|
|
141
|
+
CardTitle,
|
|
142
|
+
} from "@adamosuiteservices/ui/card";
|
|
143
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
144
|
+
|
|
145
|
+
function ControlCenter() {
|
|
146
|
+
const [deviceSettings, setDeviceSettings] = useState({
|
|
147
|
+
airplaneMode: false,
|
|
148
|
+
wifi: true,
|
|
149
|
+
bluetooth: false,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const updateSetting = (key: keyof typeof deviceSettings) => {
|
|
153
|
+
setDeviceSettings((prev) => ({ ...prev, [key]: !prev[key] }));
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<Card className="w-full max-w-sm">
|
|
158
|
+
<CardHeader>
|
|
159
|
+
<CardTitle>Control Center</CardTitle>
|
|
160
|
+
<CardDescription>Quick access to device settings</CardDescription>
|
|
161
|
+
</CardHeader>
|
|
162
|
+
<CardContent className="space-y-4">
|
|
163
|
+
<div className="grid grid-cols-2 gap-4">
|
|
164
|
+
<div className="flex flex-col items-center space-y-2 p-3 border rounded-lg">
|
|
165
|
+
<Icon symbol="flight" className="text-2xl text-muted-foreground" />
|
|
166
|
+
<span className="text-sm font-medium">Airplane</span>
|
|
167
|
+
<Switch
|
|
168
|
+
checked={deviceSettings.airplaneMode}
|
|
169
|
+
onCheckedChange={() => updateSetting("airplaneMode")}
|
|
170
|
+
className="scale-75"
|
|
171
|
+
/>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<div className="flex flex-col items-center space-y-2 p-3 border rounded-lg">
|
|
175
|
+
<Icon symbol="wifi" className="text-2xl text-muted-foreground" />
|
|
176
|
+
<span className="text-sm font-medium">Wi-Fi</span>
|
|
177
|
+
<Switch
|
|
178
|
+
checked={deviceSettings.wifi}
|
|
179
|
+
onCheckedChange={() => updateSetting("wifi")}
|
|
180
|
+
className="scale-75"
|
|
181
|
+
/>
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
<div className="flex flex-col items-center space-y-2 p-3 border rounded-lg">
|
|
185
|
+
<Icon
|
|
186
|
+
symbol="bluetooth"
|
|
187
|
+
className="text-2xl text-muted-foreground"
|
|
188
|
+
/>
|
|
189
|
+
<span className="text-sm font-medium">Bluetooth</span>
|
|
190
|
+
<Switch
|
|
191
|
+
checked={deviceSettings.bluetooth}
|
|
192
|
+
onCheckedChange={() => updateSetting("bluetooth")}
|
|
193
|
+
className="scale-75"
|
|
194
|
+
/>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
</CardContent>
|
|
198
|
+
</Card>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Privacy Settings
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
207
|
+
import { Button } from "@adamosuiteservices/ui/button";
|
|
208
|
+
|
|
209
|
+
function PrivacySettings() {
|
|
210
|
+
const [privacySettings, setPrivacySettings] = useState({
|
|
211
|
+
locationServices: true,
|
|
212
|
+
analyticsData: false,
|
|
213
|
+
crashReports: true,
|
|
214
|
+
personalizedAds: false,
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<Card className="w-full max-w-lg">
|
|
219
|
+
<CardHeader>
|
|
220
|
+
<CardTitle className="flex items-center space-x-2">
|
|
221
|
+
<Icon symbol="shield" className="text-xl" />
|
|
222
|
+
<span>Privacy & Security</span>
|
|
223
|
+
</CardTitle>
|
|
224
|
+
<CardDescription>
|
|
225
|
+
Control how your data is collected and used
|
|
226
|
+
</CardDescription>
|
|
227
|
+
</CardHeader>
|
|
228
|
+
<CardContent className="space-y-6">
|
|
229
|
+
<div className="space-y-4">
|
|
230
|
+
<div className="flex items-start justify-between space-x-4">
|
|
231
|
+
<div className="flex-1">
|
|
232
|
+
<Label className="text-sm font-medium">Location Services</Label>
|
|
233
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
234
|
+
Allow apps to access your location for personalized experiences
|
|
235
|
+
</p>
|
|
236
|
+
</div>
|
|
237
|
+
<Switch
|
|
238
|
+
checked={privacySettings.locationServices}
|
|
239
|
+
onCheckedChange={(checked) =>
|
|
240
|
+
setPrivacySettings((prev) => ({
|
|
241
|
+
...prev,
|
|
242
|
+
locationServices: checked,
|
|
243
|
+
}))
|
|
244
|
+
}
|
|
245
|
+
/>
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
<div className="flex items-start justify-between space-x-4">
|
|
249
|
+
<div className="flex-1">
|
|
250
|
+
<Label className="text-sm font-medium">
|
|
251
|
+
Analytics & Diagnostics
|
|
252
|
+
</Label>
|
|
253
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
254
|
+
Share analytics data to help improve our products
|
|
255
|
+
</p>
|
|
256
|
+
</div>
|
|
257
|
+
<Switch
|
|
258
|
+
checked={privacySettings.analyticsData}
|
|
259
|
+
onCheckedChange={(checked) =>
|
|
260
|
+
setPrivacySettings((prev) => ({
|
|
261
|
+
...prev,
|
|
262
|
+
analyticsData: checked,
|
|
263
|
+
}))
|
|
264
|
+
}
|
|
265
|
+
/>
|
|
266
|
+
</div>
|
|
267
|
+
</div>
|
|
268
|
+
|
|
269
|
+
<div className="flex justify-end space-x-2 pt-4 border-t">
|
|
270
|
+
<Button variant="outline" size="sm">
|
|
271
|
+
Reset to Defaults
|
|
272
|
+
</Button>
|
|
273
|
+
<Button size="sm">Save Changes</Button>
|
|
274
|
+
</div>
|
|
275
|
+
</CardContent>
|
|
276
|
+
</Card>
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Feature Toggles
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
function FeatureToggles() {
|
|
285
|
+
const [features, setFeatures] = useState({
|
|
286
|
+
newDashboard: false,
|
|
287
|
+
betaFeatures: false,
|
|
288
|
+
experimentalUI: false,
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const updateFeature = (key: keyof typeof features) => {
|
|
292
|
+
setFeatures((prev) => ({ ...prev, [key]: !prev[key] }));
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
return (
|
|
296
|
+
<Card className="w-full max-w-lg">
|
|
297
|
+
<CardHeader>
|
|
298
|
+
<CardTitle>Feature Toggles</CardTitle>
|
|
299
|
+
<CardDescription>
|
|
300
|
+
Enable or disable experimental features
|
|
301
|
+
</CardDescription>
|
|
302
|
+
</CardHeader>
|
|
303
|
+
<CardContent className="space-y-4">
|
|
304
|
+
<div className="flex items-start justify-between space-x-4 p-3 border rounded-lg">
|
|
305
|
+
<div className="flex-1 space-y-1">
|
|
306
|
+
<div className="flex items-center space-x-2">
|
|
307
|
+
<Label className="text-sm font-medium">New Dashboard</Label>
|
|
308
|
+
<Badge variant="default" className="text-xs">
|
|
309
|
+
New
|
|
310
|
+
</Badge>
|
|
311
|
+
</div>
|
|
312
|
+
<p className="text-xs text-muted-foreground">
|
|
313
|
+
Try our redesigned dashboard interface
|
|
314
|
+
</p>
|
|
315
|
+
</div>
|
|
316
|
+
<Switch
|
|
317
|
+
checked={features.newDashboard}
|
|
318
|
+
onCheckedChange={() => updateFeature("newDashboard")}
|
|
319
|
+
/>
|
|
320
|
+
</div>
|
|
321
|
+
|
|
322
|
+
<div className="flex items-start justify-between space-x-4 p-3 border rounded-lg">
|
|
323
|
+
<div className="flex-1 space-y-1">
|
|
324
|
+
<div className="flex items-center space-x-2">
|
|
325
|
+
<Label className="text-sm font-medium">Beta Features</Label>
|
|
326
|
+
<Badge variant="secondary" className="text-xs">
|
|
327
|
+
Beta
|
|
328
|
+
</Badge>
|
|
329
|
+
</div>
|
|
330
|
+
<p className="text-xs text-muted-foreground">
|
|
331
|
+
Access features currently in beta testing
|
|
332
|
+
</p>
|
|
333
|
+
</div>
|
|
334
|
+
<Switch
|
|
335
|
+
checked={features.betaFeatures}
|
|
336
|
+
onCheckedChange={() => updateFeature("betaFeatures")}
|
|
337
|
+
/>
|
|
338
|
+
</div>
|
|
339
|
+
</CardContent>
|
|
340
|
+
</Card>
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Deshabilitado
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
<div className="space-y-4">
|
|
349
|
+
<div className="flex items-center space-x-2">
|
|
350
|
+
<Switch disabled />
|
|
351
|
+
<Label className="text-muted-foreground">Disabled (off)</Label>
|
|
352
|
+
</div>
|
|
353
|
+
<div className="flex items-center space-x-2">
|
|
354
|
+
<Switch disabled checked />
|
|
355
|
+
<Label className="text-muted-foreground">Disabled (on)</Label>
|
|
356
|
+
</div>
|
|
357
|
+
</div>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Casos de Uso
|
|
361
|
+
|
|
362
|
+
**Settings**: On/off toggles para configuración
|
|
363
|
+
**Feature flags**: Activar/desactivar features
|
|
364
|
+
**Notifications**: Habilitar/deshabilitar notificaciones
|
|
365
|
+
**Privacy**: Controles de privacidad y permisos
|
|
366
|
+
**Device controls**: Wi-Fi, Bluetooth, Airplane mode
|
|
367
|
+
**Filters**: Mostrar/ocultar contenido
|
|
368
|
+
|
|
369
|
+
## Estilos Base
|
|
370
|
+
|
|
371
|
+
- **Size**: `h-5 w-8`
|
|
372
|
+
- **Checked bg**: `bg-primary`
|
|
373
|
+
- **Unchecked bg**: `bg-input` (dark: `bg-input/80`)
|
|
374
|
+
- **Thumb**: `size-4` con `bg-background`
|
|
375
|
+
- **Thumb checked**: `translate-x-[calc(100%-2px)]`
|
|
376
|
+
- **Thumb unchecked**: `translate-x-0`
|
|
377
|
+
- **Focus**: `ring-ring/50` con `ring-[3px]`
|
|
378
|
+
- **Transition**: `transition-all` en thumb y background
|
|
379
|
+
|
|
380
|
+
## Accesibilidad
|
|
381
|
+
|
|
382
|
+
- ✅ **Role**: `role="switch"` con `aria-checked`
|
|
383
|
+
- ✅ **Keyboard**: Space/Enter para toggle
|
|
384
|
+
- ✅ **Focus**: Focus ring visible
|
|
385
|
+
- ✅ **Label**: Asociar con `htmlFor` e `id`
|
|
386
|
+
- ✅ **State**: Screen readers anuncian checked/unchecked
|
|
387
|
+
|
|
388
|
+
## Notas de Implementación
|
|
389
|
+
|
|
390
|
+
- **Radix UI**: Basado en `@radix-ui/react-switch`
|
|
391
|
+
- **Peer class**: Usa `peer` para estilos relacionados con Label
|
|
392
|
+
- **Data states**: `data-state="checked|unchecked"` para estilos
|
|
393
|
+
- **Controlled**: Usa `checked` + `onCheckedChange`
|
|
394
|
+
- **Uncontrolled**: Usa `defaultChecked`
|
|
395
|
+
- **Dark mode**: Thumb color cambia automáticamente
|
|
396
|
+
|
|
397
|
+
## Troubleshooting
|
|
398
|
+
|
|
399
|
+
**No cambia estado**: En modo controlado usa `checked` + `onCheckedChange`, no `defaultChecked`
|
|
400
|
+
**Label no clickeable**: Asegura `htmlFor` en Label coincida con `id` del Switch
|
|
401
|
+
**Thumb no anima**: Verifica que estilos de `transition-transform` no estén sobrescritos
|
|
402
|
+
**Color incorrecto**: Switch usa `bg-primary` checked, `bg-input` unchecked
|
|
403
|
+
**Disabled no funciona**: Prop `disabled` deshabilita interacción
|
|
404
|
+
|
|
405
|
+
## Referencias
|
|
406
|
+
|
|
407
|
+
- **Radix UI Switch**: <https://www.radix-ui.com/primitives/docs/components/switch>
|
|
408
|
+
- **shadcn/ui Switch**: <https://ui.shadcn.com/docs/components/switch>
|