Slider
Elegir un número —o un rango— arrastrando, con el slider de Photos de iCloud: pista de 2 px y perilla de 14. Marcas opcionales y valor visible.
import { Slider } from "sebs7n-ui/slider"Ejemplos
Un valor, con el número a la vista
El `label` visible queda asociado al thumb por Base UI: no hace falta `aria-label`. Se mueve con las flechas, de a `largeStep` con Shift, y a los extremos con Inicio y Fin.
import { Slider } from "sebs7n-ui/slider"
import { useState } from "react"
function Basico() {
const [opacidad, setOpacidad] = useState(60)
return (
<div className="flex w-full max-w-sm flex-col gap-6">
<Slider label="Opacidad de la marca de agua" onValueChange={setOpacidad} showValue value={opacidad} />
<div
className="h-16 rounded-control bg-label"
style={{ opacity: opacidad / 100 }}
/>
</div>
)
}Rango, con marcas
`defaultValue={[min, max]}` pinta los dos thumbs solo. `minStepsBetweenValues` evita que terminen encimados, y las marcas son referencias visuales (`aria-hidden`), no topes.
import { Slider } from "sebs7n-ui/slider"
import { useState } from "react"
function Rango() {
const [precio, setPrecio] = useState<readonly number[]>([200_000, 700_000])
const formato = new Intl.NumberFormat("es-AR", { style: "currency", currency: "ARS", maximumFractionDigits: 0 })
return (
<div className="flex w-full max-w-sm flex-col gap-2">
<Slider
label="Presupuesto"
marks={[0, 250_000, 500_000, 750_000, 1_000_000]}
max={1_000_000}
min={0}
minStepsBetweenValues={1}
onValueChange={setPrecio}
step={25_000}
value={precio}
/>
<p className="text-callout text-label-secondary">
De {formato.format(precio[0])} a {formato.format(precio[1])}
</p>
</div>
)
}Tamaños, formato y deshabilitado
`sm` (32px de área arrastrable) para un panel denso; `md` (40px) suelto. `format` es el de `Intl.NumberFormat`: cambia lo que muestra `showValue` y también el `aria-valuetext` que lee el lector de pantalla.
import { Slider } from "sebs7n-ui/slider"
function TamanosYFormato() {
return (
<div className="flex w-full max-w-sm flex-col gap-6">
<Slider
defaultValue={120_000}
format={{ style: "currency", currency: "ARS", maximumFractionDigits: 0 }}
label="Tope de gasto mensual"
locale="es-AR"
max={500_000}
showValue
size="sm"
step={10_000}
/>
<Slider defaultValue={8} label="Cuotas" marks={[1, 3, 6, 12]} max={12} min={1} showValue size="md" />
<Slider defaultValue={50} disabled label="Solo lectura" showValue />
</div>
)
}Props
Generadas del TypeScript del paquete. Las propias del componente, más las heredadas del primitivo que tienen algo que explicar —marcadas «heredada de Base UI»—. El resto está en la línea «hereda de».
Slider
Hereda las props de Slider.Root.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
aria-label | string | — | Nombre accesible del elemento. |
controlClassName | string | — | Clases del área arrastrable, por si hay que cambiarle el ancho. |
defaultValue | Value | — | El valor inicial. La forma que le des acá decide si el slider es simple (40) o de rango ([20, 60]). |
label | React.ReactNode | — | Etiqueta visible. Base UI la asocia sola con los thumbs; sin ella hace falta aria-label. |
marks | readonly number[] | — | Valores donde va un punto de referencia. Siguen a min y max, no al 0–100 fijo. |
max | number | 100 | El extremo de la derecha. Por defecto, 100. |
min | number | 0 | El extremo de la izquierda. Por defecto, 0. |
showValue | boolean | false | Muestra el valor (o "20 – 60" en un rango) a la derecha de la etiqueta. |
size | "sm" | "md" | "md" | sm 24px · md 32px de área arrastrable. La pista (2 px) y la perilla (14) son las mismas en los dos. |
value | Value | — | Un número, o un array de dos para un rango. Pasarlo lo vuelve controlado. |
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
disabled | boolean | — | Heredada de Base UI. Apaga la interacción y lo marca con data-disabled, que es el atributo del que cuelgan los estilos de apagado. |
name | string | — | Heredada de Base UI. El nombre con el que el valor viaja en el submit y en el objeto errors de Form. |
onValueChange | ((value: Value extends number ? number : Value, eventDetails: SliderRoot.ChangeEventDetails) => void) | — | Heredada de Base UI. Se llama con el valor nuevo cada vez que cambia. |
orientation | "horizontal" | "vertical" | — | Heredada de Base UI. horizontal (default) o vertical. Define qué flechas mueven el foco. |
Teclado
- ← ↓
- Baja un
step. - → ↑
- Sube un
step. - Shift + flecha
- Se mueve un
largeStep(10 por defecto). - Re Pág · Av Pág
- Igual que Shift + flecha.
- Inicio · Fin
- Va al mínimo y al máximo.
- Tab
- Entra y sale. En un rango, cada thumb es su propia parada.
Accesibilidad
- Cada thumb es un
<input type="range">de verdad: el teclado y los lectores de pantalla lo tratan como el control nativo. - El
labelvisible queda asociado a los thumbs por Base UI. Sinlabel, elaria-labelque pases viaja al input, no solo al grupo. - En un rango,
aria-valuetextdistingue el thumb de inicio del de fin. - El anillo de foco va en el thumb, por fuera (como el del Switch: adentro de una perilla de 14 un anillo interior la taparía), porque el foco real vive en el input de adentro.
- La perilla es lo que se agarra: su borde de 2 px en el label llega a 3:1 contra la página en los dos temas. El área de toque la agranda un
::after(34 px, 46 con el dedo). - Las marcas son
aria-hidden: el valor lo canta el thumb, no un punto.
Reglas de uso
- Si el número exacto importa, es un `Input`. El slider es para proporciones: volumen, opacidad, un presupuesto «de tanto a tanto».
- Con
showValueel número se lee mientras se arrastra; sin él, el valor solo existe para el lector de pantalla. marksson referencias, no topes: el valor sigue siendo continuo salvo que subas elstep.- En un rango,
minStepsBetweenValuesevita que los dos thumbs terminen encimados. onValueCommittedpara lo caro (pegarle a la API):onValueChangedispara en cada píxel del arrastre.