Una lista de verificación anidada para elegir el componente correcto cuando varios parecen "lo suficientemente cerca". Úsalo antes de recurrir a shadcn/ui, MUI, Headless UI, React Native Paper o Tamagui - el primitivo equivocado bloquea la fricción que ningún estilo puede solucionar después.
¿Qué está haciendo realmente el usuario? (seleccionar, navegar, revelar, confirmar, introducir, monitorear)
¿Cuántas opciones / estados / pasos hay involucrados? (1, 2, 3–5, 6–15, 16+, ilimitado)
¿Es la opción mutuamente exclusiva o multi-selección?
¿Es el resultado reversible o destructivo? (destructivo necesita más fricción)
¿Cuál es la superficie principal - escritorio, web móvil, iOS nativo, Android nativo, o los cuatro?
¿Cuál es la modalidad de entrada? (ratón, táctil, solo teclado, lector de pantalla, voz, stylus)
¿El componente está en la ruta crítica (checkout, signup) o ambiental (configuración, filtros)?
¿Las opciones se conocen en tiempo de compilación, se obtienen una vez o se transmiten/pagina?
¿El usuario necesita comparar opciones lado a lado o escanearlas secuencialmente?
Si no puedes responder estas en una oración cada una, detente y aclara con el solicitante. Las decisiones de componentes a continuación dependen de este encuadre.
¿2 opciones que caben en una línea? → Control segmentado / Toggle Group (móvil-amigable, instantáneo, sin estado oculto). Web: ToggleGroup. Nativo: control segmentado / SegmentedButtons (Paper).
¿2–5 opciones, todas importantes de ver a la vez? → Grupo de radio. Mejor para formularios donde la opción en sí es informativa (velocidad de envío, nivel de plan).
¿6–15 opciones? → Select / Dropdown. En móvil, prefiere el <select> nativo en web y el picker nativo (Picker / ActionSheetIOS / BottomSheet) en React Native - obtienen la interfaz de rueda/hoja del nivel del SO de forma gratuita.
¿16+ opciones u obtenidas dinámicamente? → Combobox / Autocomplete con tipo para filtrar. Requerido una vez que el desplazamiento se vuelve doloroso.
¿Opciones jerárquicas o agrupadas (país → estado)? → Select en cascada o Combobox con secciones agrupadas, no radios anidados.
¿Opciones visuales (colores, avatares, plantillas)? → Tarjetas de radio o grupo de chips, no un dropdown de texto.
Gotcha móvil: un dropdown personalizado que se vea hermoso en escritorio generalmente se siente roto en un teléfono (pequeño objetivo de golpe, sin scroll de momento, sin hápticos). Por defecto, usa selectores nativos en superficies táctiles a menos que tengas una razón fuerte.
Estos tres no son intercambiables. Elige por cuándo toma efecto el cambio y qué tipo de valor representa.
¿Configuración que toma efecto inmediatamente, no se necesita envío? → Switch (p. ej. "Modo oscuro", "Notificaciones"). En nativo, usa la Switch de la plataforma - iOS y Android lo renderizan diferente y los usuarios esperan eso.
¿Uno de muchas opciones en un formulario, aplicado al enviar? → Checkbox (p. ej. "Acepto los términos", "Suscribirse a boletín").
¿Una pulsación que cambia el estado de la vista, como negrita/cursiva en un editor? → Toggle button (botón de icono con aria-pressed).
¿Una acción verdaderamente transitoria que hace algo ahora y no es un estado? → Button, no un toggle.
Accesibilidad: los switches necesitan role="switch" (web) y el correcto accessibilityRole (switch, nativo). Un checkbox estilizado como switch falla a los lectores de pantalla.
Los cuatro ocultan contenido hasta solicitado. Difieren en cuántos paneles pueden estar abiertos y si los elementos son pares.
¿Muchos elementos pares independientes, cualquier número puede estar abierto a la vez (FAQ)? → Accordion (modo multi-abierto).
¿Muchos elementos pares, solo uno abierto a la vez (especificaciones / envío / reseñas)? → Accordion (modo de un solo abierto) o Tabs - elige Tabs si los paneles tienen importancia y longitud aproximadamente iguales, Accordion si son prosa larga.
¿Una única región de mostrar/ocultar - "Mostrar más", configuración avanzada? → Collapsible (una divulgación, sin grupo).
¿Expansión pequeña en línea, se siente nativa, no se necesita estado JS? → <details> / <summary> en web. Nativo del navegador, accesibilidad gratis, SEO gratis, descubribilidad Ctrl+F gratis.
¿Contexto móvil, los paneles tienen ancho completo y el contenido es pesado? → Accordion (Tabs se vuelven abarrotados bajo ~360px).
¿Contexto móvil, el contenido es corto y la comparación lado a lado ayuda? → Tabs con scroll horizontal para desbordamiento.
Anti-patrón: tabs con 7+ elementos en móvil. Ya sea cambia a un select / scroll segmentado, o replantea la IA.
Elige por robo de enfoque, descartalidad y tamaño del contenido.
¿Bloquea la tarea completa hasta ser manejada, puede tener un formulario? → Modal / Dialog. Atrapa el enfoque, devuelve el enfoque al cerrar.
¿Panel lateral de contenido relacionado, página debajo permanece significativa? → Drawer / Sheet. En móvil, prefiere hoja inferior (alcance del pulgar); en escritorio, drawer lateral.
¿Menú contextual pequeño o información anclada a un trigger? → Popover.
¿Una línea, solo hover, etiqueta complementaria? → Tooltip. ⚠️ Los tooltips no existen en táctil - nunca pongas información crítica ahí. Los usuarios móviles la perderán.
¿Confirmando una acción destructiva? → Alert dialog (un modal más restringido con confirmar/cancelar explícito).
¿Retroalimentación limitada en tiempo después de una acción ("Guardado")? → Toast / Snackbar. No pongas acciones requeridas en un toast - se descarta automáticamente.
¿Estado persistente en página que el usuario debe reconocer? → Alert / Banner (permanece hasta ser descartado o fijado).
Regla práctica móvil: si recurrirías a un popover o tooltip en escritorio, recurre a una hoja inferior en móvil. Las superposiciones ancladas se portan mal cuando se abre el teclado.
¿Elementos que el usuario está navegando (productos, fotos, recomendaciones)? → Carousel horizontal (se empareja con swipe de pulgar en móvil, arrastre de ratón en escritorio).
¿Elementos que el usuario está consumiendo secuencialmente (historias, reels, feed)? → Carousel vertical / paginador vertical (modelo TikTok / Stories). Perfecto cuando cada elemento es a pantalla completa e inmersivo.
¿Ambos ejes se sienten plausibles (una galería)? → Horizontal, excepto en TV / pantallas grandes en landscape donde vertical se lee como una lista y horizontal se lee como destacado.
¿Más de ~10 elementos? → No carousel - cambia a un carril desplazable (sin auto-avance, sin puntos de paginación), una grid o pagination.
¿Carousel de héroe / promocional? → Considera fuertemente no construir uno. Los carousels de héroe de auto-avance tienen caídas de engagement bien documentadas; un héroe estático o dos tarjetas apiladas generalmente superan.
¿Usuario necesita linkabilidad profunda y previsibilidad de botón atrás (resultados de búsqueda)? → Pagination.
¿Feed móvil donde importa más el engagement que la navegación? → Infinite scroll, pero con un footer que sigue siendo alcanzable (usa un botón "Cargar más" al final del primer lote práctico, o expone un footer en un drawer).
¿Usuario necesita saber cuánto falta? → Botón load-more con un conteo, no infinito.
¿Formulario multi-paso / wizard? → Stepper, con un indicador de progreso visible.
¿Valor impreciso donde la sensación importa (volumen, brillo)? → Slider.
¿Valor preciso que el usuario sabe (edad, cantidad)? → Number input con inputMode="numeric" en móvil.
¿Rango de enteros pequeño, acciones ±1 se sienten naturales (cantidad del carrito)? → Stepper / NumberInput con botones ±. Los objetivos de golpe táctiles amigables son esenciales aquí (44pt mínimo).
¿Rango con dos endpoints (precio mín–precio máx)? → Range slider.
¿3–5 buckets discretos? → Control segmentado ("S / M / L / XL"), no un slider.
¿Fecha u hora? → Native picker en móvil (<input type="date"> web, DatePickerIOS / DatePickerAndroid / date picker de comunidad en RN). Los calendarios personalizados son adecuados solo cuando el rango, multi-select o reglas de negocio lo requieren.
¿La acción se acaba de completar, sin reconocimiento necesario? → Toast (3–5s).
¿Mensaje del sistema persistente ("Estás offline")? → Banner en la parte superior.
¿Problema de campo/formulario en línea? → Alerta en línea debajo del campo.
¿Error o advertencia a nivel de página? → Componente Alert en la parte superior del área de contenido.
¿Indicador numérico o booleano en otro elemento ("3 sin leer")? → Badge.
¿Contenido de carga que el usuario está a punto de ver? → Skeleton que coincida con el diseño final (no un spinner) para ganancias de rendimiento percibido.
¿Trabajo indeterminado en segundo plano? → Spinner / indicador de progreso.
Si has pasado por la lista de verificación y dos opciones aún se sienten igualmente válidas, usa estos valores predeterminados - son la elección de menor riesgo la mayoría de las veces:
Selección de tamaño desconocido → Combobox.
Toggle en una pantalla de configuración → Switch.
Toggle en un formulario enviado después → Checkbox.
Uno-de-tres modos de vista → Control segmentado.
Confirmar una acción destructiva → Alert dialog con el botón destructivo estilizado en rojo y etiquetado con el verbo ("Eliminar cuenta"), no "OK".
Superposición móvil → Hoja inferior.
Dropdown de selección única móvil → Native picker.
Lista de 50+ elementos → Lista virtualizada (react-window web, FlatList / FlashList nativo), nunca un .map() plano.