Select
BetaElige una opción —o varias— de una lista que se despliega. Mismo campo y mismos tokens que Input.
registry/ds/select.tsxPodés cursar materias en otra sede.
import { Select } from "@/registry/ds/select";
const sedes = [
{ label: "Campus Norte", value: "norte" },
{ label: "Campus Centro", value: "centro" },
{ label: "Campus Sur", value: "sur" },
{ label: "Virtual", value: "virtual" },
];
export default function SelectBasic() {
return (
<div className="w-72">
<Select label="Sede" options={sedes} placeholder="Elegí una sede" hint="Podés cursar materias en otra sede." />
</div>
);
}Cuándo usarlo
Un Select esconde las opciones: cuesta un clic verlas. Usalo cuando son muchas o cuando el espacio manda.
| Usá Select para… | Usá otra cosa para… |
|---|---|
| Elegir una entre 6 o más opciones. | 2–5 opciones que conviene comparar → Radio. |
| Formularios compactos, filtros, tablas. | Sí/No → Checkbox o Switch. |
Varias opciones de una lista larga (multiple). | Más de ~15 opciones → un buscador (Combobox, planeado). |
Estados
import { Select } from "@/registry/ds/select";
const options = [
{ label: "Primer semestre", value: "1" },
{ label: "Segundo semestre", value: "2" },
{ label: "Intensivo de verano", value: "3", disabled: true },
];
export default function SelectStates() {
return (
<div className="grid w-full max-w-xl gap-5 sm:grid-cols-2">
<Select label="Vacío" options={options} />
<Select label="Con valor" options={options} defaultValue="1" />
<Select label="Con error" required options={options} error="Elegí un período para continuar." />
<Select label="Deshabilitado" disabled options={options} defaultValue="2" />
</div>
);
}Selección múltiple
Con multiple, el menú no se cierra al elegir y cada opción muestra su
casilla. El campo resume: hasta dos nombres, después "N seleccionadas".
import { Select } from "@/registry/ds/select";
const intereses = [
{ label: "Deportes", value: "deportes" },
{ label: "Arte y cultura", value: "arte" },
{ label: "Voluntariado", value: "voluntariado" },
{ label: "Emprendimiento", value: "emprendimiento" },
{ label: "Investigación", value: "investigacion" },
];
export default function SelectMultiple() {
return (
<div className="w-72">
<Select multiple label="Intereses" options={intereses} defaultValue={["arte"]} placeholder="Elegí uno o más" />
</div>
);
}Tamaños
import { Select } from "@/registry/ds/select";
const options = [
{ label: "Mañana", value: "m" },
{ label: "Tarde", value: "t" },
{ label: "Noche", value: "n" },
];
export default function SelectSizes() {
return (
<div className="flex w-72 flex-col gap-4">
<Select size="sm" aria-label="Jornada, small" options={options} placeholder="Small · 32" />
<Select size="md" aria-label="Jornada, medium" options={options} placeholder="Medium · 40" />
<Select size="lg" aria-label="Jornada, large" options={options} placeholder="Large · 48" />
</div>
);
}Contenido
- El placeholder es una instrucción breve: "Elegí una sede". No "Seleccione…" genérico si podés ser específico.
- Opciones en orden lógico: alfabético, numérico o por frecuencia.
- Labels de opción cortos y paralelos entre sí. Sin puntuación.
- Si hay un default razonable, preseleccionalo: ahorra un paso.
- No uses una opción falsa tipo "— Ninguna —" como placeholder: si "ninguna" es válida, que sea una opción real.
Medidas
El campo mide igual que Input: alto 32 / 40 / 48, mismo padding, radius y sombra. El chevron mide 16 / 20 / 20.
| Parte | Medida |
|---|---|
| Menú | Ancho mínimo = ancho del campo · padding spacing-xs 4 · radius-md 8 · separado 4 px del campo |
Item sm | Alto mínimo 32 · px 8 · Text sm |
Item md / lg | Alto mínimo 36 · px 10 · Text sm / Text md |
| Item | radius-sm 6 · gap 8 |
| Casilla (multiple) | 16 · radius-xs 4 |
Tokens
| Parte | Propiedad | Token |
|---|---|---|
| Campo | Todos los estados | — |
| Campo · abierto | Borde + anillo 2 px | focus/ring |
| Chevron | Color | icon/subtle |
| Menú | Fondo | bg/elevated |
| Menú | Borde | border/default |
| Menú | Sombra | Elevation/lg |
| Item | Texto | text/default |
| Item resaltado | Fondo | bg/surface |
| Item elegido | Check | primary/accent |
| Casilla marcada | Fondo / check | primary/solid |
| Item deshabilitado | Texto | text/disabled |
En Figma
Cuatro piezas: Select, Multi-select (los campos), Menu (el
popover) y .Menu item. En código es un solo componente; multiple cambia
el tipo de item.
| Propiedad en Figma | Valores | En código | Nota |
|---|---|---|---|
| Select / Multi-select | Dos componentes | multiple | — |
| Size | sm · md · lg | size | — |
| State | Default · Focused · Filled · Disabled · Error · Open | disabled · error | El resto es automático. |
| Label · Hint · Required | Texto · on/off | label · hint · required | — |
| Value | Texto | value / defaultValue | — |
| .Menu item › Type | Option · Checkbox | — | Lo decide multiple. |
Instalación
npx shadcn@latest add https://polen.cdc.cool/r/select.jsonPlayground
Configurá el componente y copiá el snippet: se genera del mismo estado que renderiza el preview.
Podés cursar materias en otra sede.
<Select label="Sede" options={sedes} placeholder="Elegí una sede" hint="Podés cursar materias en otra sede." />Uso
const [sede, setSede] = useState<string | null>(null);
<Select label="Sede" options={sedes} value={sede} onValueChange={setSede} />Props
Sobre Base UI Select. Comparte
size, label, hint, error, required y disabled con Input.
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
options | { label, value, disabled? }[] | — | Las opciones. Requerido. |
multiple | boolean | false | Permite elegir varias; el valor pasa a ser string[]. |
value | string | null · string[] | — | Valor controlado. |
defaultValue | string | null · string[] | — | Valor inicial. |
onValueChange | (value) => void | — | Se llama al elegir. |
placeholder | string | "Seleccionar" | Texto cuando no hay valor. |
name | string | — | Nombre del campo en formularios nativos. |
aria-label | string | — | Nombre accesible si no hay label visible. |
Teclado
| Tecla | Qué hace |
|---|---|
| EnterEspacio↓ | Abre el menú desde el campo. |
| ↑↓ | Mueve el resaltado entre opciones. |
| HomeEnd | Primera / última opción. |
| A–Z | Salta a la opción que empieza con lo tipeado. |
| Enter | Elige la opción resaltada. |
| Esc | Cierra sin cambiar y devuelve el foco al campo. |
Qué viene resuelto
role="combobox"+listbox/optionconaria-selected.- El foco vuelve al campo al cerrar. El menú va en un portal y se reubica si no entra en pantalla.
- Label, ayuda y error asociados, igual que Input.
- Un
<input>oculto lo integra a formularios nativos.
Qué tenés que cuidar vos
- Sin
label, pasáaria-label. - En mobile con muchas opciones, considerá un
<select>nativo: el picker del sistema es más cómodo que cualquier menú custom.