@adamosuiteservices/ui 1.8.13 → 1.9.14
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/components/ui/icon/icon.d.ts +11 -0
- package/dist/components/ui/icon/icon.stories.d.ts +55 -0
- package/dist/components/ui/icon/index.d.ts +1 -0
- package/dist/components/ui/input-group/input-group.d.ts +1 -1
- package/dist/custom-layered-styles.css +1 -1
- package/dist/icon.cjs +6 -0
- package/dist/icon.js +36 -0
- package/dist/icons.css +1 -0
- package/dist/styles.css +1 -1
- package/docs/AI-GUIDE.md +321 -321
- package/docs/components/layout/sidebar.md +404 -404
- package/docs/components/layout/toaster.md +436 -436
- package/docs/components/ui/accordion-rounded.md +583 -583
- package/docs/components/ui/accordion.md +267 -267
- package/docs/components/ui/alert.md +671 -671
- package/docs/components/ui/avatar.md +588 -588
- package/docs/components/ui/badge.md +1024 -1024
- package/docs/components/ui/button-group.md +1002 -1002
- package/docs/components/ui/button.md +1078 -1078
- package/docs/components/ui/calendar.md +1159 -1159
- package/docs/components/ui/card.md +1265 -1265
- package/docs/components/ui/checkbox.md +292 -292
- package/docs/components/ui/collapsible.md +320 -320
- package/docs/components/ui/command.md +454 -454
- package/docs/components/ui/context-menu.md +540 -540
- package/docs/components/ui/dialog.md +628 -628
- package/docs/components/ui/dropdown-menu.md +731 -731
- package/docs/components/ui/field.md +706 -706
- package/docs/components/ui/hover-card.md +446 -446
- package/docs/components/ui/icon.md +502 -0
- package/docs/components/ui/input-group.md +509 -509
- 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 +142 -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 +402 -402
- package/docs/components/ui/table.md +183 -183
- 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 +243 -243
- package/docs/components/ui/tooltip.md +320 -320
- package/docs/components/ui/typography.md +191 -191
- package/package.json +6 -5
- package/dist/components/icons/account-balance-icon.d.ts +0 -3
- package/dist/components/icons/account-icon.d.ts +0 -3
- package/dist/components/icons/add-circle-icon.d.ts +0 -3
- package/dist/components/icons/alarm-icon.d.ts +0 -3
- package/dist/components/icons/archive-icon.d.ts +0 -3
- package/dist/components/icons/arrow-back-icon.d.ts +0 -3
- package/dist/components/icons/arrow-circle-up-icon.d.ts +0 -3
- package/dist/components/icons/arrow-forward-icon.d.ts +0 -3
- package/dist/components/icons/arrow-outward-icon.d.ts +0 -3
- package/dist/components/icons/article-icon.d.ts +0 -3
- package/dist/components/icons/attach-file-icon.d.ts +0 -3
- package/dist/components/icons/autorenew-icon.d.ts +0 -3
- package/dist/components/icons/bookmark-icon.d.ts +0 -3
- package/dist/components/icons/calculate-icon.d.ts +0 -3
- package/dist/components/icons/calendar-today-icon.d.ts +0 -3
- package/dist/components/icons/call-split-icon.d.ts +0 -3
- package/dist/components/icons/cancel-filled-icon.d.ts +0 -3
- package/dist/components/icons/cancel-icon.d.ts +0 -3
- package/dist/components/icons/check-circle-icon.d.ts +0 -3
- package/dist/components/icons/check-icon.d.ts +0 -3
- package/dist/components/icons/chevron-back-icon.d.ts +0 -3
- package/dist/components/icons/chevron-down-icon.d.ts +0 -3
- package/dist/components/icons/chevron-forward-icon.d.ts +0 -3
- package/dist/components/icons/chevron-up-icon.d.ts +0 -3
- package/dist/components/icons/clarify-icon.d.ts +0 -3
- package/dist/components/icons/clock-icon.d.ts +0 -3
- package/dist/components/icons/close-icon.d.ts +0 -3
- package/dist/components/icons/confirmation-number-icon.d.ts +0 -3
- package/dist/components/icons/contacts-icon.d.ts +0 -3
- package/dist/components/icons/contract-delete-icon.d.ts +0 -3
- package/dist/components/icons/copy-icon.d.ts +0 -3
- package/dist/components/icons/do-not-touch-icon.d.ts +0 -3
- package/dist/components/icons/download-icon.d.ts +0 -3
- package/dist/components/icons/dragger-icon.d.ts +0 -3
- package/dist/components/icons/edit-icon.d.ts +0 -3
- package/dist/components/icons/edit-square-icon.d.ts +0 -3
- package/dist/components/icons/exclamation-icon.d.ts +0 -3
- package/dist/components/icons/expand-circle-right-icon.d.ts +0 -3
- package/dist/components/icons/feature-search-icon.d.ts +0 -3
- package/dist/components/icons/filter-icon.d.ts +0 -3
- package/dist/components/icons/folder-icon.d.ts +0 -3
- package/dist/components/icons/folder-open-icon.d.ts +0 -3
- package/dist/components/icons/format-list-bulleted-icon.d.ts +0 -3
- package/dist/components/icons/hamburger-menu-icon.d.ts +0 -3
- package/dist/components/icons/help-icon.d.ts +0 -3
- package/dist/components/icons/hide-pass-icon.d.ts +0 -3
- package/dist/components/icons/home-icon.d.ts +0 -3
- package/dist/components/icons/id-card-icon.d.ts +0 -3
- package/dist/components/icons/index.d.ts +0 -88
- package/dist/components/icons/info-icon.d.ts +0 -3
- package/dist/components/icons/kid-star-icon.d.ts +0 -3
- package/dist/components/icons/language-icon.d.ts +0 -3
- package/dist/components/icons/last-page-icon.d.ts +0 -3
- package/dist/components/icons/layers-icon.d.ts +0 -3
- package/dist/components/icons/location-icon.d.ts +0 -3
- package/dist/components/icons/mail-icon.d.ts +0 -3
- package/dist/components/icons/manage-search-icon.d.ts +0 -3
- package/dist/components/icons/menu-icon.d.ts +0 -3
- package/dist/components/icons/message-icon.d.ts +0 -3
- package/dist/components/icons/metrics-icon.d.ts +0 -3
- package/dist/components/icons/mic-icon.d.ts +0 -3
- package/dist/components/icons/minus-icon.d.ts +0 -3
- package/dist/components/icons/mode-comment-icon.d.ts +0 -3
- package/dist/components/icons/money-icon.d.ts +0 -3
- package/dist/components/icons/monitoring-icon.d.ts +0 -3
- package/dist/components/icons/more-icon.d.ts +0 -3
- package/dist/components/icons/notifications-icon.d.ts +0 -3
- package/dist/components/icons/open-in-new-icon.d.ts +0 -3
- package/dist/components/icons/palette-icon.d.ts +0 -3
- package/dist/components/icons/password-icon.d.ts +0 -3
- package/dist/components/icons/pending-icon.d.ts +0 -3
- package/dist/components/icons/person-add-icon.d.ts +0 -3
- package/dist/components/icons/person-search-icon.d.ts +0 -3
- package/dist/components/icons/photo-icon.d.ts +0 -3
- package/dist/components/icons/plus-icon.d.ts +0 -3
- package/dist/components/icons/policy-icon.d.ts +0 -3
- package/dist/components/icons/publish-icon.d.ts +0 -3
- package/dist/components/icons/ready-icon.d.ts +0 -3
- package/dist/components/icons/receipt-icon.d.ts +0 -3
- package/dist/components/icons/receive-icon.d.ts +0 -3
- package/dist/components/icons/refresh-icon.d.ts +0 -3
- package/dist/components/icons/search-icon.d.ts +0 -3
- package/dist/components/icons/see-icon.d.ts +0 -3
- package/dist/components/icons/send-icon.d.ts +0 -3
- package/dist/components/icons/settings-icon.d.ts +0 -3
- package/dist/components/icons/shield-icon.d.ts +0 -3
- package/dist/components/icons/swap-horiz-icon.d.ts +0 -3
- package/dist/components/icons/tag-icon.d.ts +0 -3
- package/dist/components/icons/trash-icon.d.ts +0 -3
- package/dist/icons.cjs +0 -1
- package/dist/icons.js +0 -1507
|
@@ -1,243 +1,243 @@
|
|
|
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
|
-
<ItalicIcon />
|
|
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 { ItalicIcon } from "lucide-react";
|
|
44
|
-
|
|
45
|
-
<Toggle aria-label="Toggle italic">
|
|
46
|
-
<ItalicIcon />
|
|
47
|
-
</Toggle>;
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### Con Texto
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
<Toggle aria-label="Toggle bold">
|
|
54
|
-
<BoldIcon />
|
|
55
|
-
Bold
|
|
56
|
-
</Toggle>
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Variantes
|
|
60
|
-
|
|
61
|
-
```tsx
|
|
62
|
-
// Default (transparent background)
|
|
63
|
-
<Toggle aria-label="Default">
|
|
64
|
-
<ItalicIcon />
|
|
65
|
-
</Toggle>
|
|
66
|
-
|
|
67
|
-
// Outline (con border)
|
|
68
|
-
<Toggle variant="outline" aria-label="Outline">
|
|
69
|
-
<ItalicIcon />
|
|
70
|
-
</Toggle>
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Tamaños
|
|
74
|
-
|
|
75
|
-
```tsx
|
|
76
|
-
import { UnderlineIcon } from "lucide-react";
|
|
77
|
-
|
|
78
|
-
<Toggle size="sm"><UnderlineIcon /></Toggle>
|
|
79
|
-
<Toggle size="default"><UnderlineIcon /></Toggle>
|
|
80
|
-
<Toggle size="lg"><UnderlineIcon /></Toggle>
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Controlado
|
|
84
|
-
|
|
85
|
-
```tsx
|
|
86
|
-
import { useState } from "react";
|
|
87
|
-
|
|
88
|
-
function App() {
|
|
89
|
-
const [isPressed, setIsPressed] = useState(false);
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<Toggle
|
|
93
|
-
pressed={isPressed}
|
|
94
|
-
onPressedChange={setIsPressed}
|
|
95
|
-
aria-label="Toggle bold"
|
|
96
|
-
>
|
|
97
|
-
<BoldIcon />
|
|
98
|
-
{isPressed ? "Bold (On)" : "Bold (Off)"}
|
|
99
|
-
</Toggle>
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Text Editor Formatting
|
|
105
|
-
|
|
106
|
-
```tsx
|
|
107
|
-
import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react";
|
|
108
|
-
|
|
109
|
-
function TextEditor() {
|
|
110
|
-
const [formatting, setFormatting] = useState({
|
|
111
|
-
bold: false,
|
|
112
|
-
italic: false,
|
|
113
|
-
underline: false,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return (
|
|
117
|
-
<div className="flex gap-1">
|
|
118
|
-
<Toggle
|
|
119
|
-
pressed={formatting.bold}
|
|
120
|
-
onPressedChange={(pressed) =>
|
|
121
|
-
setFormatting((prev) => ({ ...prev, bold: pressed }))
|
|
122
|
-
}
|
|
123
|
-
size="sm"
|
|
124
|
-
>
|
|
125
|
-
<BoldIcon />
|
|
126
|
-
</Toggle>
|
|
127
|
-
<Toggle
|
|
128
|
-
pressed={formatting.italic}
|
|
129
|
-
onPressedChange={(pressed) =>
|
|
130
|
-
setFormatting((prev) => ({ ...prev, italic: pressed }))
|
|
131
|
-
}
|
|
132
|
-
size="sm"
|
|
133
|
-
>
|
|
134
|
-
<ItalicIcon />
|
|
135
|
-
</Toggle>
|
|
136
|
-
<Toggle
|
|
137
|
-
pressed={formatting.underline}
|
|
138
|
-
onPressedChange={(pressed) =>
|
|
139
|
-
setFormatting((prev) => ({ ...prev, underline: pressed }))
|
|
140
|
-
}
|
|
141
|
-
size="sm"
|
|
142
|
-
>
|
|
143
|
-
<UnderlineIcon />
|
|
144
|
-
</Toggle>
|
|
145
|
-
</div>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Media Controls
|
|
151
|
-
|
|
152
|
-
```tsx
|
|
153
|
-
import { MicIcon, MicOffIcon, VideoIcon, VideoOffIcon } from "lucide-react";
|
|
154
|
-
|
|
155
|
-
function MediaControls() {
|
|
156
|
-
const [media, setMedia] = useState({
|
|
157
|
-
microphone: false,
|
|
158
|
-
camera: false,
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
<div className="flex gap-3">
|
|
163
|
-
<Toggle
|
|
164
|
-
pressed={media.microphone}
|
|
165
|
-
onPressedChange={(pressed) =>
|
|
166
|
-
setMedia((prev) => ({ ...prev, microphone: pressed }))
|
|
167
|
-
}
|
|
168
|
-
variant="outline"
|
|
169
|
-
className={
|
|
170
|
-
!media.microphone ? "bg-destructive text-destructive-foreground" : ""
|
|
171
|
-
}
|
|
172
|
-
>
|
|
173
|
-
{media.microphone ? <MicIcon /> : <MicOffIcon />}
|
|
174
|
-
</Toggle>
|
|
175
|
-
|
|
176
|
-
<Toggle
|
|
177
|
-
pressed={media.camera}
|
|
178
|
-
onPressedChange={(pressed) =>
|
|
179
|
-
setMedia((prev) => ({ ...prev, camera: pressed }))
|
|
180
|
-
}
|
|
181
|
-
variant="outline"
|
|
182
|
-
className={
|
|
183
|
-
!media.camera ? "bg-destructive text-destructive-foreground" : ""
|
|
184
|
-
}
|
|
185
|
-
>
|
|
186
|
-
{media.camera ? <VideoIcon /> : <VideoOffIcon />}
|
|
187
|
-
</Toggle>
|
|
188
|
-
</div>
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### Deshabilitado
|
|
194
|
-
|
|
195
|
-
```tsx
|
|
196
|
-
<Toggle disabled><UnderlineIcon /></Toggle>
|
|
197
|
-
<Toggle disabled defaultPressed><UnderlineIcon /></Toggle>
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
## Casos de Uso
|
|
201
|
-
|
|
202
|
-
**Text formatting**: Bold, italic, underline toggles
|
|
203
|
-
**Media controls**: Mic/camera on/off
|
|
204
|
-
**View options**: List/grid view toggle
|
|
205
|
-
**Preferences**: Dark mode, notifications
|
|
206
|
-
**Filters**: Show/hide options
|
|
207
|
-
|
|
208
|
-
## Estilos Base
|
|
209
|
-
|
|
210
|
-
- **Sizes**: `h-8 min-w-8` (sm), `h-9 min-w-9` (default), `h-10 min-w-10` (lg)
|
|
211
|
-
- **State off**: `bg-transparent`
|
|
212
|
-
- **State on**: `bg-accent text-accent-foreground`
|
|
213
|
-
- **Hover**: `bg-muted text-muted-foreground`
|
|
214
|
-
- **Outline**: `border border-input shadow-xs`
|
|
215
|
-
- **Focus**: `ring-ring/50` con `ring-[3px]`
|
|
216
|
-
|
|
217
|
-
## Accesibilidad
|
|
218
|
-
|
|
219
|
-
- ✅ **Role**: `role="button"` con `aria-pressed`
|
|
220
|
-
- ✅ **ARIA**: `aria-label` requerido para icon-only
|
|
221
|
-
- ✅ **Keyboard**: Space/Enter para toggle
|
|
222
|
-
- ✅ **State**: Screen readers anuncian pressed/not pressed
|
|
223
|
-
- ✅ **Focus**: Focus ring visible
|
|
224
|
-
|
|
225
|
-
## Notas de Implementación
|
|
226
|
-
|
|
227
|
-
- **Radix UI**: Basado en `@radix-ui/react-toggle`
|
|
228
|
-
- **CVA**: Variantes con class-variance-authority
|
|
229
|
-
- **Data state**: `data-state="on|off"` para estilos
|
|
230
|
-
- **Controlled**: Usa `pressed` + `onPressedChange`
|
|
231
|
-
- **Uncontrolled**: Usa `defaultPressed`
|
|
232
|
-
|
|
233
|
-
## Troubleshooting
|
|
234
|
-
|
|
235
|
-
**Estado no cambia**: En modo controlado usa `pressed` + `onPressedChange`, no `defaultPressed`
|
|
236
|
-
**No accesible**: Agrega `aria-label` en toggles solo con iconos
|
|
237
|
-
**Estilo no actualiza**: Verifica `data-state="on"` aplicado cuando pressed
|
|
238
|
-
**Variant no funciona**: Usa `variant="outline"` o `variant="default"`
|
|
239
|
-
|
|
240
|
-
## Referencias
|
|
241
|
-
|
|
242
|
-
- **Radix UI Toggle**: <https://www.radix-ui.com/primitives/docs/components/toggle>
|
|
243
|
-
- **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
|
+
<ItalicIcon />
|
|
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 { ItalicIcon } from "lucide-react";
|
|
44
|
+
|
|
45
|
+
<Toggle aria-label="Toggle italic">
|
|
46
|
+
<ItalicIcon />
|
|
47
|
+
</Toggle>;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Con Texto
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<Toggle aria-label="Toggle bold">
|
|
54
|
+
<BoldIcon />
|
|
55
|
+
Bold
|
|
56
|
+
</Toggle>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Variantes
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
// Default (transparent background)
|
|
63
|
+
<Toggle aria-label="Default">
|
|
64
|
+
<ItalicIcon />
|
|
65
|
+
</Toggle>
|
|
66
|
+
|
|
67
|
+
// Outline (con border)
|
|
68
|
+
<Toggle variant="outline" aria-label="Outline">
|
|
69
|
+
<ItalicIcon />
|
|
70
|
+
</Toggle>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Tamaños
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import { UnderlineIcon } from "lucide-react";
|
|
77
|
+
|
|
78
|
+
<Toggle size="sm"><UnderlineIcon /></Toggle>
|
|
79
|
+
<Toggle size="default"><UnderlineIcon /></Toggle>
|
|
80
|
+
<Toggle size="lg"><UnderlineIcon /></Toggle>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Controlado
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { useState } from "react";
|
|
87
|
+
|
|
88
|
+
function App() {
|
|
89
|
+
const [isPressed, setIsPressed] = useState(false);
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<Toggle
|
|
93
|
+
pressed={isPressed}
|
|
94
|
+
onPressedChange={setIsPressed}
|
|
95
|
+
aria-label="Toggle bold"
|
|
96
|
+
>
|
|
97
|
+
<BoldIcon />
|
|
98
|
+
{isPressed ? "Bold (On)" : "Bold (Off)"}
|
|
99
|
+
</Toggle>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Text Editor Formatting
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react";
|
|
108
|
+
|
|
109
|
+
function TextEditor() {
|
|
110
|
+
const [formatting, setFormatting] = useState({
|
|
111
|
+
bold: false,
|
|
112
|
+
italic: false,
|
|
113
|
+
underline: false,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div className="flex gap-1">
|
|
118
|
+
<Toggle
|
|
119
|
+
pressed={formatting.bold}
|
|
120
|
+
onPressedChange={(pressed) =>
|
|
121
|
+
setFormatting((prev) => ({ ...prev, bold: pressed }))
|
|
122
|
+
}
|
|
123
|
+
size="sm"
|
|
124
|
+
>
|
|
125
|
+
<BoldIcon />
|
|
126
|
+
</Toggle>
|
|
127
|
+
<Toggle
|
|
128
|
+
pressed={formatting.italic}
|
|
129
|
+
onPressedChange={(pressed) =>
|
|
130
|
+
setFormatting((prev) => ({ ...prev, italic: pressed }))
|
|
131
|
+
}
|
|
132
|
+
size="sm"
|
|
133
|
+
>
|
|
134
|
+
<ItalicIcon />
|
|
135
|
+
</Toggle>
|
|
136
|
+
<Toggle
|
|
137
|
+
pressed={formatting.underline}
|
|
138
|
+
onPressedChange={(pressed) =>
|
|
139
|
+
setFormatting((prev) => ({ ...prev, underline: pressed }))
|
|
140
|
+
}
|
|
141
|
+
size="sm"
|
|
142
|
+
>
|
|
143
|
+
<UnderlineIcon />
|
|
144
|
+
</Toggle>
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Media Controls
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
import { MicIcon, MicOffIcon, VideoIcon, VideoOffIcon } from "lucide-react";
|
|
154
|
+
|
|
155
|
+
function MediaControls() {
|
|
156
|
+
const [media, setMedia] = useState({
|
|
157
|
+
microphone: false,
|
|
158
|
+
camera: false,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<div className="flex gap-3">
|
|
163
|
+
<Toggle
|
|
164
|
+
pressed={media.microphone}
|
|
165
|
+
onPressedChange={(pressed) =>
|
|
166
|
+
setMedia((prev) => ({ ...prev, microphone: pressed }))
|
|
167
|
+
}
|
|
168
|
+
variant="outline"
|
|
169
|
+
className={
|
|
170
|
+
!media.microphone ? "bg-destructive text-destructive-foreground" : ""
|
|
171
|
+
}
|
|
172
|
+
>
|
|
173
|
+
{media.microphone ? <MicIcon /> : <MicOffIcon />}
|
|
174
|
+
</Toggle>
|
|
175
|
+
|
|
176
|
+
<Toggle
|
|
177
|
+
pressed={media.camera}
|
|
178
|
+
onPressedChange={(pressed) =>
|
|
179
|
+
setMedia((prev) => ({ ...prev, camera: pressed }))
|
|
180
|
+
}
|
|
181
|
+
variant="outline"
|
|
182
|
+
className={
|
|
183
|
+
!media.camera ? "bg-destructive text-destructive-foreground" : ""
|
|
184
|
+
}
|
|
185
|
+
>
|
|
186
|
+
{media.camera ? <VideoIcon /> : <VideoOffIcon />}
|
|
187
|
+
</Toggle>
|
|
188
|
+
</div>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Deshabilitado
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
<Toggle disabled><UnderlineIcon /></Toggle>
|
|
197
|
+
<Toggle disabled defaultPressed><UnderlineIcon /></Toggle>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Casos de Uso
|
|
201
|
+
|
|
202
|
+
**Text formatting**: Bold, italic, underline toggles
|
|
203
|
+
**Media controls**: Mic/camera on/off
|
|
204
|
+
**View options**: List/grid view toggle
|
|
205
|
+
**Preferences**: Dark mode, notifications
|
|
206
|
+
**Filters**: Show/hide options
|
|
207
|
+
|
|
208
|
+
## Estilos Base
|
|
209
|
+
|
|
210
|
+
- **Sizes**: `h-8 min-w-8` (sm), `h-9 min-w-9` (default), `h-10 min-w-10` (lg)
|
|
211
|
+
- **State off**: `bg-transparent`
|
|
212
|
+
- **State on**: `bg-accent text-accent-foreground`
|
|
213
|
+
- **Hover**: `bg-muted text-muted-foreground`
|
|
214
|
+
- **Outline**: `border border-input shadow-xs`
|
|
215
|
+
- **Focus**: `ring-ring/50` con `ring-[3px]`
|
|
216
|
+
|
|
217
|
+
## Accesibilidad
|
|
218
|
+
|
|
219
|
+
- ✅ **Role**: `role="button"` con `aria-pressed`
|
|
220
|
+
- ✅ **ARIA**: `aria-label` requerido para icon-only
|
|
221
|
+
- ✅ **Keyboard**: Space/Enter para toggle
|
|
222
|
+
- ✅ **State**: Screen readers anuncian pressed/not pressed
|
|
223
|
+
- ✅ **Focus**: Focus ring visible
|
|
224
|
+
|
|
225
|
+
## Notas de Implementación
|
|
226
|
+
|
|
227
|
+
- **Radix UI**: Basado en `@radix-ui/react-toggle`
|
|
228
|
+
- **CVA**: Variantes con class-variance-authority
|
|
229
|
+
- **Data state**: `data-state="on|off"` para estilos
|
|
230
|
+
- **Controlled**: Usa `pressed` + `onPressedChange`
|
|
231
|
+
- **Uncontrolled**: Usa `defaultPressed`
|
|
232
|
+
|
|
233
|
+
## Troubleshooting
|
|
234
|
+
|
|
235
|
+
**Estado no cambia**: En modo controlado usa `pressed` + `onPressedChange`, no `defaultPressed`
|
|
236
|
+
**No accesible**: Agrega `aria-label` en toggles solo con iconos
|
|
237
|
+
**Estilo no actualiza**: Verifica `data-state="on"` aplicado cuando pressed
|
|
238
|
+
**Variant no funciona**: Usa `variant="outline"` o `variant="default"`
|
|
239
|
+
|
|
240
|
+
## Referencias
|
|
241
|
+
|
|
242
|
+
- **Radix UI Toggle**: <https://www.radix-ui.com/primitives/docs/components/toggle>
|
|
243
|
+
- **shadcn/ui Toggle**: <https://ui.shadcn.com/docs/components/toggle>
|