Saltar al contenido
EspañolEnglish
Todos los componentes (204)

Selector

Elección · Select · .amset-select

Qué es y cuándo usarlo

Un desplegable para elegir una opción de una lista. Cerrado enseña lo elegido (o el marcador); abierto, la lista con una marca en la opción elegida. Las opciones se pasan como datos (options, cada una con key y label), no como hijos: así ninguna se queda sin texto. La lista sale en la capa superior del navegador (popover), por encima de cualquier z-index y también dentro de un diálogo, y se cierra al pulsar fuera.

Cuándo usarlo

  • Una opción entre muchas que no hace falta ver a la vez: la provincia, el metal de un anillo, la forma de envío.
  • En un formulario: lleva etiqueta, ayuda (hint), error (error) y asterisco de obligatorio (required) como el resto de campos; con name, el valor viaja en un formulario nativo.
  • shortLabel en una opción cuando la etiqueta entera no cabe en la caja: «+34» en vez de «+34 · España».
  • value y onChange para controlarlo (recibe la key elegida); placeholder cambia el «Elige una opción» de serie.
  • group en una opción la mete bajo un título («Europa», «Asia»): las de un mismo grupo tienen que ir juntas en options.

Cuándo no

  • Pocas opciones que conviene ver sin abrir nada: RadioGroup.
  • Una lista larga en la que hay que buscar escribiendo: SearchField.
  • Elegir varias: MultiSelect.
  • Una lista que en el móvil conviene elegir con el selector del sistema: native, que pinta un <select> de verdad (pierde iconos y dos líneas por opción).
  • Idioma y moneda: LocalePicker, que ya los escribe bien.

Teclado: Tab llega al disparador. Cerrado, Intro, Espacio o las flechas arriba y abajo abren la lista, y el foco pasa a ella. Abierto, las flechas se mueven, Inicio y Fin van a la primera y a la última, escribir salta a la opción que empieza por esas letras, Intro o Espacio eligen y cierran, y Escape cierra: en los dos casos el foco vuelve al disparador. Las opciones deshabilitadas se saltan y no se eligen.

Accesibilidad: el disparador se llama con la etiqueta y lo elegido; la ayuda y el error se leen como su descripción. hiddenLabel deja la etiqueta solo para el lector de pantalla: es para un campo que va dentro de otro que ya se explica (el prefijo de un teléfono), nunca para ahorrar sitio. readOnly deja enfocarlo y leerlo, pero la lista no se abre. Con loading, el disparador lleva aria-busy y un anillo de carga. Con el dedo, cada opción de la lista mide al menos 44 px.

Caja de campo: tres tamaños y tres variantes (outline, soft, ghost), con el mismo hover y el mismo anillo que un TextField. El anillo sigue puesto mientras la lista está abierta, y la flecha gira.

Aspecto fino: comparte las variables de los campos, --amset-field-* (alto, relleno, radio, fondo, borde y letra), así que se ve igual que un TextField a su lado; la flecha mide --amset-select-arrow. La lista se ajusta con amset-select__panel.

Cómo se ve

Básico
ProfesionalSoporte prioritario
Empresa

<Select
  label="Plan"
  placeholder="Elige una opcion"
  options={[
    { key: 'basico', label: 'Basico' },
    { key: 'pro', label: 'Profesional', description: 'Soporte prioritario' },
    { key: 'empresa', label: 'Empresa' },
  ]}
/>

Props

Se importa con import { Select } from '@amset/ui'. Las obligatorias van marcadas.

PropTipoPara qué sirve
labelobligatoriastring—
optionsobligatoriareadonly ListOption[]—
classNamestringSe une a las clases de la biblioteca, no las sustituye.
defaultOpenbooleanLa lista empieza abierta. Para fotografiar el panel en el banco.
defaultValuestring | nullLa clave elegida al empezar, sin controlarla desde fuera.
disabledboolean—
errorstring—
excludeFromTabOrderbooleanFuera del orden del tabulador. Sigue siendo enfocable con la mano (`.focus()`), que es la diferencia con apagarlo: un control apagado no se puede enfocar de ninguna manera.
hiddenLabelbooleanLa etiqueta solo para el lector de pantalla. Para cuando el campo va dentro de otro que ya se explica solo (el prefijo de un telefono), nunca para ahorrar espacio: sin etiqueta a la vista no se sabe que se elige.
hintstring—
idstringVa al DISPARADOR, que es el nodo enfocable y el que lleva el papel del campo: es a el a quien hay que poder apuntar desde fuera con un `aria-controls`, un paso de una visita guiada o un atajo. Lo de dentro (la etiqueta, la lista, la ayuda) sigue con sus `id` propios, derivados de este cuando se pasa, para que no se repitan con dos selectores en la misma pagina.
invalidboolean—
loadingbooleanLas opciones estan llegando. Marca el campo como ocupado, enseña un anillo y una fila `loadingText` en la lista; las opciones que ya hubiera se quedan.
loadingTextstringLo que dice la fila de carga. Por defecto, «Cargando…».
namestringPara que el valor viaje en un formulario nativo.
nativebooleanUn `<select>` del SISTEMA en vez del panel propio. En un movil sale el selector de su sistema operativo, y es lo que se quiere cuando la lista es larga o se rellena con el dedo. Se pierden los iconos y las dos lineas por opcion (`renderOption`, `renderValue`, `icon`, `description`); los grupos (`group`) salen como `<optgroup>`. Mismo campo por fuera y mismas props.
offsetnumberSeparación en píxeles entre el campo y la lista. Por defecto, ninguna.
onBlur() => voidAl salir del campo. Lo usa el formulario para marcar que se ha tocado.
onChange(key: string | null) => void—
onChangeEvent(event: ChangeEvent<HTMLSelectElement>) => voidCon `native`: el evento del `<select>`, para migrar un manejador que lee `e.target.value`. `onChange` sigue entregando la clave, y se llaman los dos.
onOpenChange(open: boolean) => void—
openbooleanAbierta o cerrada, mandado desde FUERA. Con esto el estado deja de vivir aqui: quien lo pasa decide, y `onOpenChange` le avisa de cada intento. Hace falta para abrir la lista desde otro sitio -un atajo de teclado, un paso de una visita guiada- sin tocar el disparador.
panelWidth"content" | "trigger"Cuánto mide la lista de ancho. `trigger` (por defecto) la deja igual que el campo, que es lo que se espera de un selector normal. `content` la deja crecer hasta que quepan las opciones. Hace falta cuando el disparador es a propósito MÁS ESTRECHO que las opciones: el prefijo de un teléfono enseña «+34» y la lista dice «+34 · España». Medido antes de existir esto: el panel salía de 69 px y las 19 opciones aparecían cortadas a media palabra («Españ», «Portug»).
placeholderstringTexto cuando no hay nada elegido. No sustituye a la etiqueta.
placementPlacementDónde sale la lista. Por defecto, pegada justo debajo del campo.
readOnlyboolean—
renderOptionOptionRender<ListOption>Pinta el interior de cada opcion de la lista: un avatar, dos lineas, un precio. El nombre que lee el lector de pantalla sigue siendo `label`.
renderValue(option: SelectOption) => ReactNodePinta lo elegido dentro del campo cerrado. Sin esto sale el icono y la etiqueta (o `shortLabel`). Lo que se anuncia es lo que se pinte, asi que conviene que lleve el texto.
requiredboolean—
shouldCloseOnSelectbooleanElegir una opcion NO cierra la lista. Por defecto la cierra, que es lo que espera cualquiera en un desplegable de una sola opcion; esto es para quien monta encima algo que deja seguir mirando.
size"sm" | "md" | "lg"—
validationBehavior"aria" | "native"—
valuestring | nullLa clave elegida, controlada desde fuera.
variantFieldVariant—

Acepta además los atributos del elemento que pinta: className, style, data-*, aria-* y sus eventos.

Mandos

Estas variables CSS son la forma de adaptarlo. Se declaran sobre el selector del componente, no en :root: la hoja las redeclara en la propia regla y una declaración en el mismo elemento gana siempre.

VariablePor defecto
--amset-select-arrow1rem

Cómo se cambia

.amset-select {
  --amset-select-arrow: ...;
}

En el banco de pruebas

Cada estado y cada variante, para tocarlos de uno en uno, en su ficha de ui.amset.tech: