@adamosuiteservices/ui 2.13.2 → 2.13.3

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 (34) hide show
  1. package/dist/components/ui/slider/slider.d.ts +5 -2
  2. package/dist/slider.cjs +6 -7
  3. package/dist/slider.js +191 -177
  4. package/docs/AI-GUIDE.md +321 -321
  5. package/docs/components/layout/sidebar.md +399 -399
  6. package/docs/components/layout/toaster.md +436 -436
  7. package/docs/components/ui/accordion-rounded.md +584 -584
  8. package/docs/components/ui/accordion.md +269 -269
  9. package/docs/components/ui/calendar.md +1159 -1159
  10. package/docs/components/ui/card.md +1455 -1455
  11. package/docs/components/ui/checkbox.md +292 -292
  12. package/docs/components/ui/collapsible.md +323 -323
  13. package/docs/components/ui/dialog.md +628 -628
  14. package/docs/components/ui/field.md +706 -706
  15. package/docs/components/ui/hover-card.md +446 -446
  16. package/docs/components/ui/kbd.md +434 -434
  17. package/docs/components/ui/label.md +359 -359
  18. package/docs/components/ui/pagination.md +650 -650
  19. package/docs/components/ui/popover.md +536 -536
  20. package/docs/components/ui/progress.md +182 -182
  21. package/docs/components/ui/radio-group.md +311 -311
  22. package/docs/components/ui/separator.md +214 -214
  23. package/docs/components/ui/sheet.md +174 -174
  24. package/docs/components/ui/skeleton.md +140 -140
  25. package/docs/components/ui/slider.md +460 -341
  26. package/docs/components/ui/spinner.md +170 -170
  27. package/docs/components/ui/switch.md +408 -408
  28. package/docs/components/ui/tabs-underline.md +106 -106
  29. package/docs/components/ui/tabs.md +122 -122
  30. package/docs/components/ui/textarea.md +243 -243
  31. package/docs/components/ui/toggle.md +237 -237
  32. package/docs/components/ui/tooltip.md +317 -317
  33. package/docs/components/ui/typography.md +320 -320
  34. package/package.json +1 -1
@@ -1,341 +1,460 @@
1
- # Slider
2
-
3
- Control de rango con thumbs deslizables. Soporta valores simples y rangos. Basado en Radix UI.
4
-
5
- ## Descripción
6
-
7
- El componente `Slider` permite seleccionar un valor arrastrando un control deslizante.
8
-
9
- ## Importación
10
-
11
- ```typescript
12
- import { Slider } from "@adamosuiteservices/ui/slider";
13
- ```
14
-
15
- ## Anatomía
16
-
17
- ```tsx
18
- <Slider defaultValue={[50]} max={100} step={1} />
19
- ```
20
-
21
- **Componentes**: 1 (Slider) con 3 partes internas (Root, Track, Range, Thumb)
22
-
23
- ## Props
24
-
25
- | Prop | Tipo | Descripción |
26
- | --------------- | ---------------------------- | ----------------------------------- |
27
- | `defaultValue` | `number[]` | Valor inicial (uncontrolled) |
28
- | `value` | `number[]` | Valor controlado (array de números) |
29
- | `onValueChange` | `(value: number[]) => void` | Callback al cambiar valor |
30
- | `min` | `number` | Valor mínimo (default: 0) |
31
- | `max` | `number` | Valor máximo (default: 100) |
32
- | `step` | `number` | Incremento (default: 1) |
33
- | `disabled` | `boolean` | Deshabilita el slider |
34
- | `orientation` | `"horizontal" \| "vertical"` | Orientación (default: horizontal) |
35
- | `theme` | `Theme` | Tema personalizado |
36
- | `className` | `string` | Clases CSS adicionales |
37
-
38
- **Nota**: `value` y `defaultValue` siempre son arrays. Single value = `[50]`, range = `[20, 80]`
39
-
40
- ## Patrones de Uso
41
-
42
- ### Básico
43
-
44
- ```tsx
45
- import { Slider } from "@adamosuiteservices/ui/slider";
46
-
47
- <Slider defaultValue={[33]} max={100} step={1} className="w-[60%]" />;
48
- ```
49
-
50
- ### Con Label
51
-
52
- ```tsx
53
- import { Label } from "@adamosuiteservices/ui/label";
54
- import { useState } from "react";
55
-
56
- function App() {
57
- const [value, setValue] = useState([50]);
58
-
59
- return (
60
- <div className="grid w-full max-w-sm items-center gap-2">
61
- <Label htmlFor="volume">Volume: {value[0]}%</Label>
62
- <Slider
63
- id="volume"
64
- max={100}
65
- step={1}
66
- value={value}
67
- onValueChange={setValue}
68
- className="w-full"
69
- />
70
- </div>
71
- );
72
- }
73
- ```
74
-
75
- ### Range (Dos Valores)
76
-
77
- ```tsx
78
- function App() {
79
- const [value, setValue] = useState([20, 80]);
80
-
81
- return (
82
- <div className="grid w-full max-w-sm items-center gap-2">
83
- <Label>
84
- Price Range: ${value[0]} - ${value[1]}
85
- </Label>
86
- <Slider
87
- max={100}
88
- step={1}
89
- value={value}
90
- onValueChange={setValue}
91
- className="w-full"
92
- />
93
- </div>
94
- );
95
- }
96
- ```
97
-
98
- ### Con Steps
99
-
100
- ```tsx
101
- function App() {
102
- const [value, setValue] = useState([25]);
103
- const stepSize = 25;
104
-
105
- return (
106
- <div className="grid w-full max-w-sm items-center gap-2">
107
- <Label>Progress: {value[0]}%</Label>
108
- <Slider
109
- max={100}
110
- step={stepSize}
111
- value={value}
112
- onValueChange={setValue}
113
- className="w-full"
114
- />
115
- <div className="flex justify-between text-xs text-muted-foreground">
116
- <span>0%</span>
117
- <span>25%</span>
118
- <span>50%</span>
119
- <span>75%</span>
120
- <span>100%</span>
121
- </div>
122
- </div>
123
- );
124
- }
125
- ```
126
-
127
- ### Vertical
128
-
129
- ```tsx
130
- function App() {
131
- const [value, setValue] = useState([60]);
132
-
133
- return (
134
- <div className="flex h-64 items-center space-x-6">
135
- <div className="flex flex-col items-center space-y-2">
136
- <Label>Volume</Label>
137
- <Slider
138
- orientation="vertical"
139
- max={100}
140
- step={1}
141
- value={value}
142
- onValueChange={setValue}
143
- className="h-48"
144
- />
145
- <span className="text-sm text-muted-foreground">{value[0]}%</span>
146
- </div>
147
- </div>
148
- );
149
- }
150
- ```
151
-
152
- ### Con Botones
153
-
154
- ```tsx
155
- import { Button } from "@adamosuiteservices/ui/button";
156
-
157
- function App() {
158
- const [value, setValue] = useState([50]);
159
-
160
- const decrease = () => setValue([Math.max(0, value[0] - 10)]);
161
- const increase = () => setValue([Math.min(100, value[0] + 10)]);
162
-
163
- return (
164
- <div className="grid w-full max-w-sm items-center gap-4">
165
- <Label>Volume: {value[0]}%</Label>
166
- <div className="flex items-center space-x-2">
167
- <Button
168
- variant="outline"
169
- size="sm"
170
- onClick={decrease}
171
- disabled={value[0] === 0}
172
- >
173
- -
174
- </Button>
175
- <Slider
176
- value={value}
177
- onValueChange={setValue}
178
- max={100}
179
- step={1}
180
- className="flex-1"
181
- />
182
- <Button
183
- variant="outline"
184
- size="sm"
185
- onClick={increase}
186
- disabled={value[0] === 100}
187
- >
188
- +
189
- </Button>
190
- </div>
191
- </div>
192
- );
193
- }
194
- ```
195
-
196
- ### Price Filter
197
-
198
- ```tsx
199
- import {
200
- Card,
201
- CardContent,
202
- CardHeader,
203
- CardTitle,
204
- } from "@adamosuiteservices/ui/card";
205
- import { Button } from "@adamosuiteservices/ui/button";
206
-
207
- function PriceFilter() {
208
- const [priceRange, setPriceRange] = useState([25, 75]);
209
-
210
- return (
211
- <Card className="w-full max-w-sm">
212
- <CardHeader>
213
- <CardTitle>Filter by Price</CardTitle>
214
- </CardHeader>
215
- <CardContent className="space-y-4">
216
- <div className="space-y-2">
217
- <Label>Price Range</Label>
218
- <Slider
219
- value={priceRange}
220
- onValueChange={setPriceRange}
221
- max={100}
222
- step={1}
223
- className="w-full"
224
- />
225
- </div>
226
- <div className="flex justify-between text-sm">
227
- <span>${priceRange[0]}</span>
228
- <span>${priceRange[1]}</span>
229
- </div>
230
- <Button className="w-full">Apply Filter</Button>
231
- </CardContent>
232
- </Card>
233
- );
234
- }
235
- ```
236
-
237
- ### RGB Color Picker
238
-
239
- ```tsx
240
- function ColorPicker() {
241
- const [red, setRed] = useState([128]);
242
- const [green, setGreen] = useState([200]);
243
- const [blue, setBlue] = useState([75]);
244
-
245
- const rgbColor = `rgb(${red[0]}, ${green[0]}, ${blue[0]})`;
246
-
247
- return (
248
- <Card className="w-full max-w-sm">
249
- <CardHeader>
250
- <CardTitle>RGB Color Picker</CardTitle>
251
- </CardHeader>
252
- <CardContent className="space-y-6">
253
- <div
254
- className="w-full h-20 rounded-lg border"
255
- style={{ backgroundColor: rgbColor }}
256
- />
257
-
258
- <div className="space-y-4">
259
- <div className="space-y-2">
260
- <div className="flex justify-between">
261
- <Label>Red</Label>
262
- <span className="text-sm text-muted-foreground">{red[0]}</span>
263
- </div>
264
- <Slider value={red} onValueChange={setRed} max={255} step={1} />
265
- </div>
266
-
267
- <div className="space-y-2">
268
- <div className="flex justify-between">
269
- <Label>Green</Label>
270
- <span className="text-sm text-muted-foreground">{green[0]}</span>
271
- </div>
272
- <Slider value={green} onValueChange={setGreen} max={255} step={1} />
273
- </div>
274
-
275
- <div className="space-y-2">
276
- <div className="flex justify-between">
277
- <Label>Blue</Label>
278
- <span className="text-sm text-muted-foreground">{blue[0]}</span>
279
- </div>
280
- <Slider value={blue} onValueChange={setBlue} max={255} step={1} />
281
- </div>
282
- </div>
283
- </CardContent>
284
- </Card>
285
- );
286
- }
287
- ```
288
-
289
- ### Deshabilitado
290
-
291
- ```tsx
292
- <Slider defaultValue={[50]} max={100} step={1} disabled className="w-full" />
293
- ```
294
-
295
- ## Casos de Uso
296
-
297
- **Volume control**: Audio, música, efectos de sonido
298
- **Price filters**: Rango de precios en e-commerce
299
- **Color pickers**: RGB, HSL sliders
300
- **Brightness/Contrast**: Ajustes de imagen
301
- **Temperature**: Termostatos, controles de clima
302
- **Range selection**: Filtros de fecha, edad, tamaño
303
-
304
- ## Estilos Base
305
-
306
- - **Track height**: `h-1.5` (horizontal), `w-1.5` (vertical)
307
- - **Track bg**: `bg-muted`
308
- - **Range bg**: `bg-primary`
309
- - **Thumb**: `size-4` con `border-primary`, `bg-white`, `shadow-sm`
310
- - **Thumb hover/focus**: `ring-4` con `ring-ring/50`
311
- - **Vertical**: `min-h-44` default, `flex-col`
312
-
313
- ## Accesibilidad
314
-
315
- - **Role**: `role="slider"` con `aria-valuenow`, `aria-valuemin`, `aria-valuemax`
316
- - ✅ **Keyboard**: Arrow keys para ajustar valor, Home/End para min/max
317
- - ✅ **Focus**: Focus ring visible en thumbs
318
- - **Label**: Asociar con `id` para screen readers
319
-
320
- ## Notas de Implementación
321
-
322
- - **Radix UI**: Basado en `@radix-ui/react-slider`
323
- - **Multiple thumbs**: Array length determina número de thumbs
324
- - **Value format**: Siempre array, ej: `[50]` para single, `[20, 80]` para range
325
- - **Auto-thumbs**: Genera thumbs automáticamente basado en `value.length`
326
- - **Data attributes**: `data-orientation` para estilos horizontal/vertical
327
- - **Theme support**: Prop `theme` para personalización
328
-
329
- ## Troubleshooting
330
-
331
- **Thumb no se mueve**: Verifica `max`, `min` y `step` son números válidos
332
- **Value no actualiza**: En modo controlado usa `value` + `onValueChange`, no `defaultValue`
333
- **Range invertido**: Asegura `value[0] < value[1]` en ranges
334
- **Vertical no funciona**: Agrega `className="h-[Xpx]"` para altura explícita
335
- **Step no funciona**: `step` debe ser divisor válido del rango (max - min)
336
- **Multiple thumbs**: `value={[10, 50, 90]}` crea 3 thumbs
337
-
338
- ## Referencias
339
-
340
- - **Radix UI Slider**: <https://www.radix-ui.com/primitives/docs/components/slider>
341
- - **shadcn/ui Slider**: <https://ui.shadcn.com/docs/components/slider>
1
+ # Slider
2
+
3
+ Control de rango con thumbs deslizables. Soporta valores simples y rangos. Basado en Radix UI.
4
+
5
+ ## Descripción
6
+
7
+ El componente `Slider` permite seleccionar un valor arrastrando un control deslizante.
8
+
9
+ ## Importación
10
+
11
+ ```typescript
12
+ import { Slider } from "@adamosuiteservices/ui/slider";
13
+ ```
14
+
15
+ ## Anatomía
16
+
17
+ ```tsx
18
+ <Slider defaultValue={[50]} max={100} step={1} />
19
+ ```
20
+
21
+ **Componentes**: 1 (Slider) con 3 partes internas (Root, Track, Range, Thumb)
22
+
23
+ ## Props
24
+
25
+ | Prop | Tipo | Descripción |
26
+ | --------------- | ----------------------------------- | ----------------------------------- |
27
+ | `defaultValue` | `number[]` | Valor inicial (uncontrolled) |
28
+ | `value` | `number[]` | Valor controlado (array de números) |
29
+ | `onValueChange` | `(value: number[]) => void` | Callback al cambiar valor |
30
+ | `min` | `number` | Valor mínimo (default: 0) |
31
+ | `max` | `number` | Valor máximo (default: 100) |
32
+ | `step` | `number` | Incremento (default: 1) |
33
+ | `disabled` | `boolean` | Deshabilita el slider |
34
+ | `orientation` | `"horizontal" \| "vertical"` | Orientación (default: horizontal) |
35
+ | `color` | `"full" \| [string, string]` | Gradiente de colores personalizado |
36
+ | `theme` | `Theme` | Tema personalizado |
37
+ | `className` | `string` | Clases CSS adicionales |
38
+
39
+ **Nota**: `value` y `defaultValue` siempre son arrays. Single value = `[50]`, range = `[20, 80]`
40
+
41
+ ## Patrones de Uso
42
+
43
+ ### Básico
44
+
45
+ ```tsx
46
+ import { Slider } from "@adamosuiteservices/ui/slider";
47
+
48
+ <Slider defaultValue={[33]} max={100} step={1} className="w-[60%]" />;
49
+ ```
50
+
51
+ ### Con Label
52
+
53
+ ```tsx
54
+ import { Label } from "@adamosuiteservices/ui/label";
55
+ import { useState } from "react";
56
+
57
+ function App() {
58
+ const [value, setValue] = useState([50]);
59
+
60
+ return (
61
+ <div className="grid w-full max-w-sm items-center gap-2">
62
+ <Label htmlFor="volume">Volume: {value[0]}%</Label>
63
+ <Slider
64
+ id="volume"
65
+ max={100}
66
+ step={1}
67
+ value={value}
68
+ onValueChange={setValue}
69
+ className="w-full"
70
+ />
71
+ </div>
72
+ );
73
+ }
74
+ ```
75
+
76
+ ### Range (Dos Valores)
77
+
78
+ ```tsx
79
+ function App() {
80
+ const [value, setValue] = useState([20, 80]);
81
+
82
+ return (
83
+ <div className="grid w-full max-w-sm items-center gap-2">
84
+ <Label>
85
+ Price Range: ${value[0]} - ${value[1]}
86
+ </Label>
87
+ <Slider
88
+ max={100}
89
+ step={1}
90
+ value={value}
91
+ onValueChange={setValue}
92
+ className="w-full"
93
+ />
94
+ </div>
95
+ );
96
+ }
97
+ ```
98
+
99
+ ### Con Steps
100
+
101
+ ```tsx
102
+ function App() {
103
+ const [value, setValue] = useState([25]);
104
+ const stepSize = 25;
105
+
106
+ return (
107
+ <div className="grid w-full max-w-sm items-center gap-2">
108
+ <Label>Progress: {value[0]}%</Label>
109
+ <Slider
110
+ max={100}
111
+ step={stepSize}
112
+ value={value}
113
+ onValueChange={setValue}
114
+ className="w-full"
115
+ />
116
+ <div className="flex justify-between text-xs text-muted-foreground">
117
+ <span>0%</span>
118
+ <span>25%</span>
119
+ <span>50%</span>
120
+ <span>75%</span>
121
+ <span>100%</span>
122
+ </div>
123
+ </div>
124
+ );
125
+ }
126
+ ```
127
+
128
+ ### Vertical
129
+
130
+ ```tsx
131
+ function App() {
132
+ const [value, setValue] = useState([60]);
133
+
134
+ return (
135
+ <div className="flex h-64 items-center space-x-6">
136
+ <div className="flex flex-col items-center space-y-2">
137
+ <Label>Volume</Label>
138
+ <Slider
139
+ orientation="vertical"
140
+ max={100}
141
+ step={1}
142
+ value={value}
143
+ onValueChange={setValue}
144
+ className="h-48"
145
+ />
146
+ <span className="text-sm text-muted-foreground">{value[0]}%</span>
147
+ </div>
148
+ </div>
149
+ );
150
+ }
151
+ ```
152
+
153
+ ### Con Botones
154
+
155
+ ```tsx
156
+ import { Button } from "@adamosuiteservices/ui/button";
157
+
158
+ function App() {
159
+ const [value, setValue] = useState([50]);
160
+
161
+ const decrease = () => setValue([Math.max(0, value[0] - 10)]);
162
+ const increase = () => setValue([Math.min(100, value[0] + 10)]);
163
+
164
+ return (
165
+ <div className="grid w-full max-w-sm items-center gap-4">
166
+ <Label>Volume: {value[0]}%</Label>
167
+ <div className="flex items-center space-x-2">
168
+ <Button
169
+ variant="outline"
170
+ size="sm"
171
+ onClick={decrease}
172
+ disabled={value[0] === 0}
173
+ >
174
+ -
175
+ </Button>
176
+ <Slider
177
+ value={value}
178
+ onValueChange={setValue}
179
+ max={100}
180
+ step={1}
181
+ className="flex-1"
182
+ />
183
+ <Button
184
+ variant="outline"
185
+ size="sm"
186
+ onClick={increase}
187
+ disabled={value[0] === 100}
188
+ >
189
+ +
190
+ </Button>
191
+ </div>
192
+ </div>
193
+ );
194
+ }
195
+ ```
196
+
197
+ ### Price Filter
198
+
199
+ ```tsx
200
+ import {
201
+ Card,
202
+ CardContent,
203
+ CardHeader,
204
+ CardTitle,
205
+ } from "@adamosuiteservices/ui/card";
206
+ import { Button } from "@adamosuiteservices/ui/button";
207
+
208
+ function PriceFilter() {
209
+ const [priceRange, setPriceRange] = useState([25, 75]);
210
+
211
+ return (
212
+ <Card className="w-full max-w-sm">
213
+ <CardHeader>
214
+ <CardTitle>Filter by Price</CardTitle>
215
+ </CardHeader>
216
+ <CardContent className="space-y-4">
217
+ <div className="space-y-2">
218
+ <Label>Price Range</Label>
219
+ <Slider
220
+ value={priceRange}
221
+ onValueChange={setPriceRange}
222
+ max={100}
223
+ step={1}
224
+ className="w-full"
225
+ />
226
+ </div>
227
+ <div className="flex justify-between text-sm">
228
+ <span>${priceRange[0]}</span>
229
+ <span>${priceRange[1]}</span>
230
+ </div>
231
+ <Button className="w-full">Apply Filter</Button>
232
+ </CardContent>
233
+ </Card>
234
+ );
235
+ }
236
+ ```
237
+
238
+ ### RGB Color Picker
239
+
240
+ ```tsx
241
+ function ColorPicker() {
242
+ const [red, setRed] = useState([128]);
243
+ const [green, setGreen] = useState([200]);
244
+ const [blue, setBlue] = useState([75]);
245
+
246
+ const rgbColor = `rgb(${red[0]}, ${green[0]}, ${blue[0]})`;
247
+
248
+ return (
249
+ <Card className="w-full max-w-sm">
250
+ <CardHeader>
251
+ <CardTitle>RGB Color Picker</CardTitle>
252
+ </CardHeader>
253
+ <CardContent className="space-y-6">
254
+ <div
255
+ className="w-full h-20 rounded-lg border"
256
+ style={{ backgroundColor: rgbColor }}
257
+ />
258
+
259
+ <div className="space-y-4">
260
+ <div className="space-y-2">
261
+ <div className="flex justify-between">
262
+ <Label>Red</Label>
263
+ <span className="text-sm text-muted-foreground">{red[0]}</span>
264
+ </div>
265
+ <Slider value={red} onValueChange={setRed} max={255} step={1} />
266
+ </div>
267
+
268
+ <div className="space-y-2">
269
+ <div className="flex justify-between">
270
+ <Label>Green</Label>
271
+ <span className="text-sm text-muted-foreground">{green[0]}</span>
272
+ </div>
273
+ <Slider value={green} onValueChange={setGreen} max={255} step={1} />
274
+ </div>
275
+
276
+ <div className="space-y-2">
277
+ <div className="flex justify-between">
278
+ <Label>Blue</Label>
279
+ <span className="text-sm text-muted-foreground">{blue[0]}</span>
280
+ </div>
281
+ <Slider value={blue} onValueChange={setBlue} max={255} step={1} />
282
+ </div>
283
+ </div>
284
+ </CardContent>
285
+ </Card>
286
+ );
287
+ }
288
+ ```
289
+
290
+ ### Con Gradiente Arcoíris
291
+
292
+ ```tsx
293
+ function RainbowSlider() {
294
+ const [value, setValue] = useState([50]);
295
+
296
+ ## Casos de Uso
297
+
298
+ **Volume control**: Audio, música, efectos de sonido
299
+ **Price filters**: Rango de precios en e-commerce
300
+ **Color pickers**: RGB, HSL sliders con gradientes personalizados
301
+ **Brightness/Contrast**: Ajustes de imagen
302
+ **Temperature**: Termostatos, controles de clima con gradientes frío-calor
303
+ **Range selection**: Filtros de fecha, edad, tamaño
304
+ **Hue selection**: Selectores de tono con gradiente arcoíris
305
+ ## Estilos Base
306
+
307
+ - **Track height**: `h-1.5` (horizontal), `w-1.5` (vertical)
308
+ - **Track bg**: `bg-muted` (o gradiente personalizado con prop `color`)
309
+ - **Range bg**: `bg-primary` (transparente cuando se usa `color`)
310
+ - **Thumb**: `size-4` con `border-primary`, `bg-white`, `shadow-sm`
311
+ - **Thumb hover/focus**: `ring-4` con `ring-ring/50`
312
+ - **Vertical**: `min-h-44` default, `flex-col`
313
+ - **Gradiente full**: Arcoíris de 6 colores (rojo → amarillo → verde → cyan → azul → rojo)
314
+ - **Gradiente personalizado**: Linear gradient entre dos colores especificados
315
+ ### Con Colores Personalizados
316
+
317
+ ```tsx
318
+ function CustomColorSlider() {
319
+ const [value, setValue] = useState([60]);
320
+
321
+ return (
322
+ <div className="space-y-6 w-full max-w-sm">
323
+ {/* Púrpura a Rosa */}
324
+ <div className="space-y-2">
325
+ <Label>Purple to Pink: {value[0]}%</Label>
326
+ <Slider
327
+ color={["#8b5cf6", "#ec4899"]}
328
+ value={value}
329
+ onValueChange={setValue}
330
+ ## Troubleshooting
331
+
332
+ **Thumb no se mueve**: Verifica `max`, `min` y `step` son números válidos
333
+ **Value no actualiza**: En modo controlado usa `value` + `onValueChange`, no `defaultValue`
334
+ **Range invertido**: Asegura `value[0] < value[1]` en ranges
335
+ **Vertical no funciona**: Agrega `className="h-[Xpx]"` para altura explícita
336
+ **Step no funciona**: `step` debe ser divisor válido del rango (max - min)
337
+ **Multiple thumbs**: `value={[10, 50, 90]}` crea 3 thumbs
338
+ **Color no se aplica**: Prop `color` acepta `"full"` o array de 2 strings `["#color1", "#color2"]`
339
+ **Gradiente no visible**: Asegura que los colores sean válidos (hex, rgb, hsl, etc.)
340
+ <Label>Blue to Green</Label>
341
+ <Slider
342
+ color={["#3b82f6", "#10b981"]}
343
+ defaultValue={[40]}
344
+ max={100}
345
+ step={1}
346
+ className="w-full"
347
+ />
348
+ </div>
349
+
350
+ {/* Naranja a Rojo */}
351
+ <div className="space-y-2">
352
+ <Label>Orange to Red</Label>
353
+ <Slider
354
+ color={["#f97316", "#ef4444"]}
355
+ defaultValue={[75]}
356
+ max={100}
357
+ step={1}
358
+ className="w-full"
359
+ />
360
+ </div>
361
+ </div>
362
+ );
363
+ }
364
+ ```
365
+
366
+ ### Control de Temperatura con Colores
367
+
368
+ ```tsx
369
+ import { Badge } from "@adamosuiteservices/ui/badge";
370
+
371
+ function ColorfulTemperature() {
372
+ const [temperature, setTemperature] = useState([72]);
373
+
374
+ return (
375
+ <Card className="w-full max-w-sm">
376
+ <CardHeader>
377
+ <CardTitle>Temperature Control</CardTitle>
378
+ </CardHeader>
379
+ <CardContent className="space-y-4">
380
+ <div className="text-center">
381
+ <div className="text-3xl font-bold">{temperature[0]}°F</div>
382
+ <Badge variant="secondary" className="mt-2">
383
+ Cold to Hot
384
+ </Badge>
385
+ </div>
386
+ <div className="space-y-2">
387
+ <Label>Target Temperature</Label>
388
+ <Slider
389
+ color={["#3b82f6", "#ef4444"]}
390
+ value={temperature}
391
+ onValueChange={setTemperature}
392
+ min={50}
393
+ max={90}
394
+ step={1}
395
+ className="w-full"
396
+ />
397
+ </div>
398
+ <div className="flex justify-between text-xs text-muted-foreground">
399
+ <span>❄️ 50°F</span>
400
+ <span>🔥 90°F</span>
401
+ </div>
402
+ </CardContent>
403
+ </Card>
404
+ );
405
+ }
406
+ ```
407
+
408
+ ### Deshabilitado
409
+
410
+ ```tsx
411
+ <Slider defaultValue={[50]} max={100} step={1} disabled className="w-full" />
412
+ ```
413
+
414
+ ## Casos de Uso
415
+
416
+ **Volume control**: Audio, música, efectos de sonido
417
+ **Price filters**: Rango de precios en e-commerce
418
+ **Color pickers**: RGB, HSL sliders
419
+ **Brightness/Contrast**: Ajustes de imagen
420
+ **Temperature**: Termostatos, controles de clima
421
+ **Range selection**: Filtros de fecha, edad, tamaño
422
+
423
+ ## Estilos Base
424
+
425
+ - **Track height**: `h-1.5` (horizontal), `w-1.5` (vertical)
426
+ - **Track bg**: `bg-muted`
427
+ - **Range bg**: `bg-primary`
428
+ - **Thumb**: `size-4` con `border-primary`, `bg-white`, `shadow-sm`
429
+ - **Thumb hover/focus**: `ring-4` con `ring-ring/50`
430
+ - **Vertical**: `min-h-44` default, `flex-col`
431
+
432
+ ## Accesibilidad
433
+
434
+ - ✅ **Role**: `role="slider"` con `aria-valuenow`, `aria-valuemin`, `aria-valuemax`
435
+ - ✅ **Keyboard**: Arrow keys para ajustar valor, Home/End para min/max
436
+ - ✅ **Focus**: Focus ring visible en thumbs
437
+ - ✅ **Label**: Asociar con `id` para screen readers
438
+
439
+ ## Notas de Implementación
440
+
441
+ - **Radix UI**: Basado en `@radix-ui/react-slider`
442
+ - **Multiple thumbs**: Array length determina número de thumbs
443
+ - **Value format**: Siempre array, ej: `[50]` para single, `[20, 80]` para range
444
+ - **Auto-thumbs**: Genera thumbs automáticamente basado en `value.length`
445
+ - **Data attributes**: `data-orientation` para estilos horizontal/vertical
446
+ - **Theme support**: Prop `theme` para personalización
447
+
448
+ ## Troubleshooting
449
+
450
+ **Thumb no se mueve**: Verifica `max`, `min` y `step` son números válidos
451
+ **Value no actualiza**: En modo controlado usa `value` + `onValueChange`, no `defaultValue`
452
+ **Range invertido**: Asegura `value[0] < value[1]` en ranges
453
+ **Vertical no funciona**: Agrega `className="h-[Xpx]"` para altura explícita
454
+ **Step no funciona**: `step` debe ser divisor válido del rango (max - min)
455
+ **Multiple thumbs**: `value={[10, 50, 90]}` crea 3 thumbs
456
+
457
+ ## Referencias
458
+
459
+ - **Radix UI Slider**: <https://www.radix-ui.com/primitives/docs/components/slider>
460
+ - **shadcn/ui Slider**: <https://ui.shadcn.com/docs/components/slider>