Select · single value
El Select es la respuesta a una pregunta cerrada. Su desafío no es visual sino combinatorio: cómo presentar entre tres y cien opciones de forma que el usuario encuentre la suya en menos de dos segundos, sin perder accesibilidad, sin reinventar el control nativo cuando este basta. Esta ficha documenta el contrato del Select en mayo de 2026.
Decomposición del componente
Las seis capas del componente
01 · Átomo color.neutral.950 · color.neutral.200 · space.10 · space.8 · radius.sm · duration.140 Primitivos compartidos con el resto de inputs. El Select no inventa.
02 · Compuesto color.surface.input.bg · color.surface.menu.bg · color.surface.menu.option-hover · space.menu.option.y · motion.menu.expand Semánticos: fondo del control, fondo del menú desplegado, hover de opción, padding de cada item, animación del expand.
03 · Regla native-first policy · combobox WAI-ARIA 1.2 · Zod enum · Floating UI para posicionamiento Governance: si el listado ≤12 opciones usa <select> nativo; si supera, combobox custom con pattern completo (aria-expanded, aria-controls, aria-activedescendant).
04 · Pieza <Select options={enum} value={x} /> Schema cerrado sobre enum. Un agente que proponga un value fuera del enum recibe rechazo OPA.
05 · Familia Inputs / Form fields · emparentado con Combobox editable y MultiSelect El Select single-value es el canon. Los parientes (Combobox editable, MultiSelect) se bifurcan con schema y governance propios.
06 · Estado reposo · hover · focus-visible · open · searchable · multi · loading · disabled · agent-aware open y searchable son los estados que más varían; multi se activa solo en la variant MultiSelect.
Tokens consumidos
Semánticos
color.surface.input.bg oklch(0.99 0.005 75) Fondo del control en reposo
color.surface.menu.bg oklch(0.97 0.01 75) Fondo del menú desplegado, ligero offset visual
color.surface.menu.option-hover oklch(0.92 0.01 75) Estado hover de cada opción del menú
color.border.input.default oklch(0.78 0.005 75) Borde unificado con resto de inputs
space.menu.option.y 0.5rem Padding vertical de cada opción, hit-target 44px
motion.menu.expand { duration: 140ms, easing: cubic-bezier(0.2, 0, 0.38, 1) } Expansión del menú, deshabilitada con prefers-reduced-motion
Técnicas de governance aplicadas
Técnicas activas
Native-first
Por defecto el componente renderiza <select> nativo. Solo cuando hay búsqueda, agrupación, o más de 12 opciones, se promueve a combobox custom WAI-ARIA. La regla evita reinventar accesibilidad en el 80% de los casos.
Combobox WAI-ARIA
Cuando el listado supera el umbral, el componente custom implementa el patrón combobox completo: aria-expanded, aria-controls, aria-activedescendant, navegación con flechas, búsqueda por tecla, escape para cerrar.
Schema enumerado
Un agente que componga un Select tiene que elegir un valor del enum. Si propone uno fuera, OPA rechaza. La governance rompe la tentación clásica de los LLM de inventar opciones plausibles.
Estado físico
Agentic-consumable desde noviembre de 2025. Las opciones se exponen vía MCP como enum cerrado. El agente no puede ampliar el rango sin un cambio governance-firmado.
Estados soportados
hover, focus-visible, disabled, loading (durante carga asíncrona de opciones), multi-select (variant), searchable (variant), agent-aware. El estado searchable se activa automáticamente cuando el rango supera 12 opciones.
Composiciones prohibidas
Reglas activas
value fuera del enum
Un agente no puede componer <Select value='beta-custom'> si beta-custom no está en options. La alternativa: ampliar el enum vía change request governance-firmado.
Más de 12 opciones en <select> nativo
Se promueve a combobox custom con búsqueda. Warning en CI si la composición ignora la regla.
Select con opciones vacías
Un Select con 0 o 1 opción no tiene sentido semántico. Alternativa: texto estático, o Input readonly si el valor es informativo.
Interoperabilidad
- Consumido por:
FormRow,InlineFilters,Toolbar(como selector de vista),SettingsPanel. - Consume:
Label,HelperText, internamenteOption(no exportable; es la unidad del enum). - Con qué compone mal: dentro de
Tooltip(el menú del Select se abre dentro del tooltip, colisiona con el dismiss), y como hijo directo deModalsi el menú excede el viewport del modal. - Sustituibles por:
Radiosi hay ≤5 opciones y el usuario debe verlas todas;Combobox editablesi el valor puede estar fuera del enum;MultiSelectsi se aceptan varios.
Medición propuesta
Eventos planificados
select.open
Atributos: options count, searchable, origin. Detecta Selects con menú abierto varias veces sin selección (fricción).
select.search_used
Si el ratio supera 60%, el umbral de promoción a searchable podría bajarse de 12 a 8 opciones.
Mutación plástica (Estado 3)
Qué muta y qué permanece
Reordenación contextual options-order = derive(historial-local) Las opciones más usadas por el lector suben al principio, sin ocultar ninguna. El orden del enum canónico se mantiene como fuente; la presentación se reordena localmente.
Apertura del menú direction = derive(posición-viewport) Floating UI decide si abre hacia arriba o hacia abajo según espacio disponible. Agnóstico al lector.
Búsqueda activable searchable = derive(options.length × locale) El umbral 12 opciones baja en idiomas donde cada opción es más larga (alemán).
Fijo por contract schema enum · aria-expanded · aria-activedescendant · Escape para cerrar Nunca mutan. El patrón WAI-ARIA combobox es inviolable.
Rollback automático si la reordenación propone ocultar una opción o si el searchable se desactiva cuando debería estar activo (más de 12 opciones visibles). El lector nunca pierde visibilidad del rango completo.
Genealogía
Árbol de evolución
<select> nativo
Sin componente. Estilizado con CSS dentro de los límites del control nativo.
Consumidor Diseñador y desarrollador
Componente React custom
Reescrito como <Select /> con menú custom para soportar búsqueda. Rompió accesibilidad en mobile.
Consumidor Producto · 6 productos
Política native-first
Marcha atrás. Se vuelve a <select> nativo por defecto. El custom queda como variant promovida bajo umbral.
Consumidor Producto · 22 productos
Select.AI · expuesto vía MCP
Enum publicado vía MCP. Agente tier-2 puede componer formularios con Select cerrado.
Consumidor Humano + agente tier-1 + agente tier-2
Select plástico
planificadoReordenación contextual del listado según historia local del usuario. Sin ocultar opciones; solo reordenando lo más usado al principio.
Consumidor Estado 3
Notas del editor
Descartes catalogados
Variants rechazadas
variant='cascading' Selects encadenados (país → región → ciudad) generaban estados intermedios difíciles de validar y de explicar a un agente. Sustituido por componente <CascadingSelect /> separado con su propio contrato.
variant='editable' Combobox que permite escribir valores fuera del enum. Conflicto con la regla de cierre estricto del schema. Movido a un componente <Combobox editable=true /> distinto.
Referencias cruzadas
- Familia: Inputs / Form fields.
- Componente hermano: Nº 0250 · Checkbox.
- Estado al que pertenece: Estado 2 · Agéntico.