@adamosuiteservices/ui 2.13.4 → 2.14.1
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/{button-Bn4LFAa9.js → button-B0lWuG-D.js} +27 -18
- package/dist/{button-Day6_fbu.cjs → button-DVrteFz9.cjs} +2 -2
- package/dist/button.cjs +1 -1
- package/dist/button.js +1 -1
- package/dist/{calendar-B1_ybTg0.js → calendar-CfqtuOWv.js} +1 -1
- package/dist/{calendar-CZkzHgYi.cjs → calendar-CpUN6BGK.cjs} +1 -1
- package/dist/calendar.cjs +1 -1
- package/dist/calendar.js +1 -1
- package/dist/colors.css +1 -1
- package/dist/{combobox-BOi7QzmO.js → combobox-B8HMlZy6.js} +1 -1
- package/dist/{combobox-0ndFo07_.cjs → combobox-Btj-hiBy.cjs} +1 -1
- package/dist/combobox.cjs +1 -1
- package/dist/combobox.js +1 -1
- package/dist/components/ui/alert/alert.d.ts +1 -1
- package/dist/components/ui/button/button.d.ts +3 -2
- package/dist/components/ui/card/card.d.ts +2 -2
- package/dist/date-picker-selector.cjs +1 -1
- package/dist/date-picker-selector.js +3 -3
- package/dist/file-upload.cjs +1 -1
- package/dist/file-upload.js +1 -1
- package/dist/full-screen-loader.cjs +1 -1
- package/dist/full-screen-loader.js +1 -1
- package/dist/input-group.cjs +1 -1
- package/dist/input-group.js +1 -1
- package/dist/pagination.cjs +1 -1
- package/dist/pagination.js +1 -1
- package/dist/sidebar.cjs +1 -1
- package/dist/sidebar.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/tabs.cjs +14 -16
- package/dist/tabs.js +17 -19
- package/docs/AI-GUIDE.md +321 -321
- package/docs/components/layout/full-screen-loader.md +2 -2
- 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/button.md +35 -23
- 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/dialog.md +628 -628
- package/docs/components/ui/field.md +706 -706
- package/docs/components/ui/hover-card.md +446 -446
- 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/separator.md +214 -214
- package/docs/components/ui/sheet.md +174 -174
- package/docs/components/ui/skeleton.md +140 -140
- 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 +125 -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 +320 -320
- package/package.json +1 -1
|
@@ -1,237 +1,237 @@
|
|
|
1
|
-
# Toggle
|
|
2
|
-
|
|
3
|
-
Botón de dos estados (on/off). Basado en Radix UI con variantes CVA.
|
|
4
|
-
|
|
5
|
-
## Descripción
|
|
6
|
-
|
|
7
|
-
El componente `Toggle` es un botón de dos estados (presionado/no presionado).
|
|
8
|
-
|
|
9
|
-
## Importación
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
import { Toggle } from "@adamosuiteservices/ui/toggle";
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Anatomía
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
<Toggle aria-label="Toggle italic">
|
|
19
|
-
<Icon symbol="format_italic" />
|
|
20
|
-
</Toggle>
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
**Componentes**: 1 (Toggle)
|
|
24
|
-
|
|
25
|
-
## Props
|
|
26
|
-
|
|
27
|
-
| Prop | Tipo | Descripción |
|
|
28
|
-
| ----------------- | ---------------------------- | ----------------------------- |
|
|
29
|
-
| `defaultPressed` | `boolean` | Estado inicial (uncontrolled) |
|
|
30
|
-
| `pressed` | `boolean` | Estado controlado |
|
|
31
|
-
| `onPressedChange` | `(pressed: boolean) => void` | Callback al cambiar |
|
|
32
|
-
| `disabled` | `boolean` | Deshabilita el toggle |
|
|
33
|
-
| `variant` | `"default" \| "outline"` | Estilo visual |
|
|
34
|
-
| `size` | `"sm" \| "default" \| "lg"` | Tamaño del toggle |
|
|
35
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
36
|
-
|
|
37
|
-
## Patrones de Uso
|
|
38
|
-
|
|
39
|
-
### Básico
|
|
40
|
-
|
|
41
|
-
```tsx
|
|
42
|
-
import { Toggle } from "@adamosuiteservices/ui/toggle";
|
|
43
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
44
|
-
|
|
45
|
-
<Toggle aria-label="Toggle italic">
|
|
46
|
-
<Icon symbol="format_italic" />
|
|
47
|
-
</Toggle>;
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### Con Texto
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
<Toggle aria-label="Toggle bold">
|
|
54
|
-
<Icon symbol="format_bold" />
|
|
55
|
-
Bold
|
|
56
|
-
</Toggle>
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Variantes
|
|
60
|
-
|
|
61
|
-
```tsx
|
|
62
|
-
// Default (transparent background)
|
|
63
|
-
<Toggle aria-label="Default">
|
|
64
|
-
<Icon symbol="format_italic" />
|
|
65
|
-
</Toggle>
|
|
66
|
-
|
|
67
|
-
// Outline (con border)
|
|
68
|
-
<Toggle variant="outline" aria-label="Outline">
|
|
69
|
-
<Icon symbol="format_italic" />
|
|
70
|
-
</Toggle>
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Tamaños
|
|
74
|
-
|
|
75
|
-
```tsx
|
|
76
|
-
<Toggle size="sm"><Icon symbol="format_underlined" /></Toggle>
|
|
77
|
-
<Toggle size="default"><Icon symbol="format_underlined" /></Toggle>
|
|
78
|
-
<Toggle size="lg"><Icon symbol="format_underlined" /></Toggle>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Controlado
|
|
82
|
-
|
|
83
|
-
```tsx
|
|
84
|
-
import { useState } from "react";
|
|
85
|
-
|
|
86
|
-
function App() {
|
|
87
|
-
const [isPressed, setIsPressed] = useState(false);
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
<Toggle
|
|
91
|
-
pressed={isPressed}
|
|
92
|
-
onPressedChange={setIsPressed}
|
|
93
|
-
aria-label="Toggle bold"
|
|
94
|
-
>
|
|
95
|
-
<Icon symbol="format_bold" />
|
|
96
|
-
{isPressed ? "Bold (On)" : "Bold (Off)"}
|
|
97
|
-
</Toggle>
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Text Editor Formatting
|
|
103
|
-
|
|
104
|
-
```tsx
|
|
105
|
-
function TextEditor() {
|
|
106
|
-
const [formatting, setFormatting] = useState({
|
|
107
|
-
bold: false,
|
|
108
|
-
italic: false,
|
|
109
|
-
underline: false,
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<div className="flex gap-1">
|
|
114
|
-
<Toggle
|
|
115
|
-
pressed={formatting.bold}
|
|
116
|
-
onPressedChange={(pressed) =>
|
|
117
|
-
setFormatting((prev) => ({ ...prev, bold: pressed }))
|
|
118
|
-
}
|
|
119
|
-
size="sm"
|
|
120
|
-
>
|
|
121
|
-
<Icon symbol="format_bold" />
|
|
122
|
-
</Toggle>
|
|
123
|
-
<Toggle
|
|
124
|
-
pressed={formatting.italic}
|
|
125
|
-
onPressedChange={(pressed) =>
|
|
126
|
-
setFormatting((prev) => ({ ...prev, italic: pressed }))
|
|
127
|
-
}
|
|
128
|
-
size="sm"
|
|
129
|
-
>
|
|
130
|
-
<Icon symbol="format_italic" />
|
|
131
|
-
</Toggle>
|
|
132
|
-
<Toggle
|
|
133
|
-
pressed={formatting.underline}
|
|
134
|
-
onPressedChange={(pressed) =>
|
|
135
|
-
setFormatting((prev) => ({ ...prev, underline: pressed }))
|
|
136
|
-
}
|
|
137
|
-
size="sm"
|
|
138
|
-
>
|
|
139
|
-
<Icon symbol="format_underlined" />
|
|
140
|
-
</Toggle>
|
|
141
|
-
</div>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### Media Controls
|
|
147
|
-
|
|
148
|
-
```tsx
|
|
149
|
-
function MediaControls() {
|
|
150
|
-
const [media, setMedia] = useState({
|
|
151
|
-
microphone: false,
|
|
152
|
-
camera: false,
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
return (
|
|
156
|
-
<div className="flex gap-3">
|
|
157
|
-
<Toggle
|
|
158
|
-
pressed={media.microphone}
|
|
159
|
-
onPressedChange={(pressed) =>
|
|
160
|
-
setMedia((prev) => ({ ...prev, microphone: pressed }))
|
|
161
|
-
}
|
|
162
|
-
variant="outline"
|
|
163
|
-
className={
|
|
164
|
-
!media.microphone ? "bg-destructive text-destructive-foreground" : ""
|
|
165
|
-
}
|
|
166
|
-
>
|
|
167
|
-
<Icon symbol={media.microphone ? "mic" : "mic_off"} />
|
|
168
|
-
</Toggle>
|
|
169
|
-
|
|
170
|
-
<Toggle
|
|
171
|
-
pressed={media.camera}
|
|
172
|
-
onPressedChange={(pressed) =>
|
|
173
|
-
setMedia((prev) => ({ ...prev, camera: pressed }))
|
|
174
|
-
}
|
|
175
|
-
variant="outline"
|
|
176
|
-
className={
|
|
177
|
-
!media.camera ? "bg-destructive text-destructive-foreground" : ""
|
|
178
|
-
}
|
|
179
|
-
>
|
|
180
|
-
<Icon symbol={media.camera ? "videocam" : "videocam_off"} />
|
|
181
|
-
</Toggle>
|
|
182
|
-
</div>
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### Deshabilitado
|
|
188
|
-
|
|
189
|
-
```tsx
|
|
190
|
-
<Toggle disabled><Icon symbol="format_underlined" /></Toggle>
|
|
191
|
-
<Toggle disabled defaultPressed><Icon symbol="format_underlined" /></Toggle>
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
## Casos de Uso
|
|
195
|
-
|
|
196
|
-
**Text formatting**: Bold, italic, underline toggles
|
|
197
|
-
**Media controls**: Mic/camera on/off
|
|
198
|
-
**View options**: List/grid view toggle
|
|
199
|
-
**Preferences**: Dark mode, notifications
|
|
200
|
-
**Filters**: Show/hide options
|
|
201
|
-
|
|
202
|
-
## Estilos Base
|
|
203
|
-
|
|
204
|
-
- **Sizes**: `h-8 min-w-8` (sm), `h-9 min-w-9` (default), `h-10 min-w-10` (lg)
|
|
205
|
-
- **State off**: `bg-transparent`
|
|
206
|
-
- **State on**: `bg-accent text-accent-foreground`
|
|
207
|
-
- **Hover**: `bg-muted text-muted-foreground`
|
|
208
|
-
- **Outline**: `border border-input shadow-xs`
|
|
209
|
-
- **Focus**: `ring-ring/50` con `ring-[3px]`
|
|
210
|
-
|
|
211
|
-
## Accesibilidad
|
|
212
|
-
|
|
213
|
-
- ✅ **Role**: `role="button"` con `aria-pressed`
|
|
214
|
-
- ✅ **ARIA**: `aria-label` requerido para icon-only
|
|
215
|
-
- ✅ **Keyboard**: Space/Enter para toggle
|
|
216
|
-
- ✅ **State**: Screen readers anuncian pressed/not pressed
|
|
217
|
-
- ✅ **Focus**: Focus ring visible
|
|
218
|
-
|
|
219
|
-
## Notas de Implementación
|
|
220
|
-
|
|
221
|
-
- **Radix UI**: Basado en `@radix-ui/react-toggle`
|
|
222
|
-
- **CVA**: Variantes con class-variance-authority
|
|
223
|
-
- **Data state**: `data-state="on|off"` para estilos
|
|
224
|
-
- **Controlled**: Usa `pressed` + `onPressedChange`
|
|
225
|
-
- **Uncontrolled**: Usa `defaultPressed`
|
|
226
|
-
|
|
227
|
-
## Troubleshooting
|
|
228
|
-
|
|
229
|
-
**Estado no cambia**: En modo controlado usa `pressed` + `onPressedChange`, no `defaultPressed`
|
|
230
|
-
**No accesible**: Agrega `aria-label` en toggles solo con iconos
|
|
231
|
-
**Estilo no actualiza**: Verifica `data-state="on"` aplicado cuando pressed
|
|
232
|
-
**Variant no funciona**: Usa `variant="outline"` o `variant="default"`
|
|
233
|
-
|
|
234
|
-
## Referencias
|
|
235
|
-
|
|
236
|
-
- **Radix UI Toggle**: <https://www.radix-ui.com/primitives/docs/components/toggle>
|
|
237
|
-
- **shadcn/ui Toggle**: <https://ui.shadcn.com/docs/components/toggle>
|
|
1
|
+
# Toggle
|
|
2
|
+
|
|
3
|
+
Botón de dos estados (on/off). Basado en Radix UI con variantes CVA.
|
|
4
|
+
|
|
5
|
+
## Descripción
|
|
6
|
+
|
|
7
|
+
El componente `Toggle` es un botón de dos estados (presionado/no presionado).
|
|
8
|
+
|
|
9
|
+
## Importación
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { Toggle } from "@adamosuiteservices/ui/toggle";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Anatomía
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
<Toggle aria-label="Toggle italic">
|
|
19
|
+
<Icon symbol="format_italic" />
|
|
20
|
+
</Toggle>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Componentes**: 1 (Toggle)
|
|
24
|
+
|
|
25
|
+
## Props
|
|
26
|
+
|
|
27
|
+
| Prop | Tipo | Descripción |
|
|
28
|
+
| ----------------- | ---------------------------- | ----------------------------- |
|
|
29
|
+
| `defaultPressed` | `boolean` | Estado inicial (uncontrolled) |
|
|
30
|
+
| `pressed` | `boolean` | Estado controlado |
|
|
31
|
+
| `onPressedChange` | `(pressed: boolean) => void` | Callback al cambiar |
|
|
32
|
+
| `disabled` | `boolean` | Deshabilita el toggle |
|
|
33
|
+
| `variant` | `"default" \| "outline"` | Estilo visual |
|
|
34
|
+
| `size` | `"sm" \| "default" \| "lg"` | Tamaño del toggle |
|
|
35
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
36
|
+
|
|
37
|
+
## Patrones de Uso
|
|
38
|
+
|
|
39
|
+
### Básico
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { Toggle } from "@adamosuiteservices/ui/toggle";
|
|
43
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
44
|
+
|
|
45
|
+
<Toggle aria-label="Toggle italic">
|
|
46
|
+
<Icon symbol="format_italic" />
|
|
47
|
+
</Toggle>;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Con Texto
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<Toggle aria-label="Toggle bold">
|
|
54
|
+
<Icon symbol="format_bold" />
|
|
55
|
+
Bold
|
|
56
|
+
</Toggle>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Variantes
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
// Default (transparent background)
|
|
63
|
+
<Toggle aria-label="Default">
|
|
64
|
+
<Icon symbol="format_italic" />
|
|
65
|
+
</Toggle>
|
|
66
|
+
|
|
67
|
+
// Outline (con border)
|
|
68
|
+
<Toggle variant="outline" aria-label="Outline">
|
|
69
|
+
<Icon symbol="format_italic" />
|
|
70
|
+
</Toggle>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Tamaños
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
<Toggle size="sm"><Icon symbol="format_underlined" /></Toggle>
|
|
77
|
+
<Toggle size="default"><Icon symbol="format_underlined" /></Toggle>
|
|
78
|
+
<Toggle size="lg"><Icon symbol="format_underlined" /></Toggle>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Controlado
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { useState } from "react";
|
|
85
|
+
|
|
86
|
+
function App() {
|
|
87
|
+
const [isPressed, setIsPressed] = useState(false);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<Toggle
|
|
91
|
+
pressed={isPressed}
|
|
92
|
+
onPressedChange={setIsPressed}
|
|
93
|
+
aria-label="Toggle bold"
|
|
94
|
+
>
|
|
95
|
+
<Icon symbol="format_bold" />
|
|
96
|
+
{isPressed ? "Bold (On)" : "Bold (Off)"}
|
|
97
|
+
</Toggle>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Text Editor Formatting
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
function TextEditor() {
|
|
106
|
+
const [formatting, setFormatting] = useState({
|
|
107
|
+
bold: false,
|
|
108
|
+
italic: false,
|
|
109
|
+
underline: false,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div className="flex gap-1">
|
|
114
|
+
<Toggle
|
|
115
|
+
pressed={formatting.bold}
|
|
116
|
+
onPressedChange={(pressed) =>
|
|
117
|
+
setFormatting((prev) => ({ ...prev, bold: pressed }))
|
|
118
|
+
}
|
|
119
|
+
size="sm"
|
|
120
|
+
>
|
|
121
|
+
<Icon symbol="format_bold" />
|
|
122
|
+
</Toggle>
|
|
123
|
+
<Toggle
|
|
124
|
+
pressed={formatting.italic}
|
|
125
|
+
onPressedChange={(pressed) =>
|
|
126
|
+
setFormatting((prev) => ({ ...prev, italic: pressed }))
|
|
127
|
+
}
|
|
128
|
+
size="sm"
|
|
129
|
+
>
|
|
130
|
+
<Icon symbol="format_italic" />
|
|
131
|
+
</Toggle>
|
|
132
|
+
<Toggle
|
|
133
|
+
pressed={formatting.underline}
|
|
134
|
+
onPressedChange={(pressed) =>
|
|
135
|
+
setFormatting((prev) => ({ ...prev, underline: pressed }))
|
|
136
|
+
}
|
|
137
|
+
size="sm"
|
|
138
|
+
>
|
|
139
|
+
<Icon symbol="format_underlined" />
|
|
140
|
+
</Toggle>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Media Controls
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
function MediaControls() {
|
|
150
|
+
const [media, setMedia] = useState({
|
|
151
|
+
microphone: false,
|
|
152
|
+
camera: false,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<div className="flex gap-3">
|
|
157
|
+
<Toggle
|
|
158
|
+
pressed={media.microphone}
|
|
159
|
+
onPressedChange={(pressed) =>
|
|
160
|
+
setMedia((prev) => ({ ...prev, microphone: pressed }))
|
|
161
|
+
}
|
|
162
|
+
variant="outline"
|
|
163
|
+
className={
|
|
164
|
+
!media.microphone ? "bg-destructive text-destructive-foreground" : ""
|
|
165
|
+
}
|
|
166
|
+
>
|
|
167
|
+
<Icon symbol={media.microphone ? "mic" : "mic_off"} />
|
|
168
|
+
</Toggle>
|
|
169
|
+
|
|
170
|
+
<Toggle
|
|
171
|
+
pressed={media.camera}
|
|
172
|
+
onPressedChange={(pressed) =>
|
|
173
|
+
setMedia((prev) => ({ ...prev, camera: pressed }))
|
|
174
|
+
}
|
|
175
|
+
variant="outline"
|
|
176
|
+
className={
|
|
177
|
+
!media.camera ? "bg-destructive text-destructive-foreground" : ""
|
|
178
|
+
}
|
|
179
|
+
>
|
|
180
|
+
<Icon symbol={media.camera ? "videocam" : "videocam_off"} />
|
|
181
|
+
</Toggle>
|
|
182
|
+
</div>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Deshabilitado
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
<Toggle disabled><Icon symbol="format_underlined" /></Toggle>
|
|
191
|
+
<Toggle disabled defaultPressed><Icon symbol="format_underlined" /></Toggle>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Casos de Uso
|
|
195
|
+
|
|
196
|
+
**Text formatting**: Bold, italic, underline toggles
|
|
197
|
+
**Media controls**: Mic/camera on/off
|
|
198
|
+
**View options**: List/grid view toggle
|
|
199
|
+
**Preferences**: Dark mode, notifications
|
|
200
|
+
**Filters**: Show/hide options
|
|
201
|
+
|
|
202
|
+
## Estilos Base
|
|
203
|
+
|
|
204
|
+
- **Sizes**: `h-8 min-w-8` (sm), `h-9 min-w-9` (default), `h-10 min-w-10` (lg)
|
|
205
|
+
- **State off**: `bg-transparent`
|
|
206
|
+
- **State on**: `bg-accent text-accent-foreground`
|
|
207
|
+
- **Hover**: `bg-muted text-muted-foreground`
|
|
208
|
+
- **Outline**: `border border-input shadow-xs`
|
|
209
|
+
- **Focus**: `ring-ring/50` con `ring-[3px]`
|
|
210
|
+
|
|
211
|
+
## Accesibilidad
|
|
212
|
+
|
|
213
|
+
- ✅ **Role**: `role="button"` con `aria-pressed`
|
|
214
|
+
- ✅ **ARIA**: `aria-label` requerido para icon-only
|
|
215
|
+
- ✅ **Keyboard**: Space/Enter para toggle
|
|
216
|
+
- ✅ **State**: Screen readers anuncian pressed/not pressed
|
|
217
|
+
- ✅ **Focus**: Focus ring visible
|
|
218
|
+
|
|
219
|
+
## Notas de Implementación
|
|
220
|
+
|
|
221
|
+
- **Radix UI**: Basado en `@radix-ui/react-toggle`
|
|
222
|
+
- **CVA**: Variantes con class-variance-authority
|
|
223
|
+
- **Data state**: `data-state="on|off"` para estilos
|
|
224
|
+
- **Controlled**: Usa `pressed` + `onPressedChange`
|
|
225
|
+
- **Uncontrolled**: Usa `defaultPressed`
|
|
226
|
+
|
|
227
|
+
## Troubleshooting
|
|
228
|
+
|
|
229
|
+
**Estado no cambia**: En modo controlado usa `pressed` + `onPressedChange`, no `defaultPressed`
|
|
230
|
+
**No accesible**: Agrega `aria-label` en toggles solo con iconos
|
|
231
|
+
**Estilo no actualiza**: Verifica `data-state="on"` aplicado cuando pressed
|
|
232
|
+
**Variant no funciona**: Usa `variant="outline"` o `variant="default"`
|
|
233
|
+
|
|
234
|
+
## Referencias
|
|
235
|
+
|
|
236
|
+
- **Radix UI Toggle**: <https://www.radix-ui.com/primitives/docs/components/toggle>
|
|
237
|
+
- **shadcn/ui Toggle**: <https://ui.shadcn.com/docs/components/toggle>
|