Sistema de Entrada Numérica y Stepper
Propósito
El Sistema de Entrada Numérica y Stepper proporciona un marco estandarizado para diseñar, estructurar e implementar controles utilizados para seleccionar, ajustar o introducir valores numéricos discretos. La entrada numérica precisa (como cantidades de artículos en el carrito, asignaciones de licencias SaaS, unidades de niveles de precios, rangos de presupuesto o especificaciones de dimensiones) requiere equilibrar microajustes rápidos con edición de texto directa, estados claros de límite mínimo/máximo, zonas táctiles adaptadas al tacto y accesibilidad completa para teclado y lectores de pantalla.
Los controles HTML estándar <input type="number"> se renderizan de forma inconsistente en los diferentes navegadores, a menudo con pequeñas flechas de spinner nativas no personalizables que violan las pautas de zonas táctiles (WCAG 2.2 SC 2.5.8) y provocan ajustes de desplazamiento accidentales. Este skill define patrones de UI explícitos, reglas de diseño espacial, estados de interacción y estándares de accesibilidad para steppers numéricos personalizados y campos con unidades acotadas.
Casos de Uso
- Selectores de Cantidad en Carrito de Compras: Permitir a los compradores incrementar, decrementar o escribir fácilmente la cantidad de productos en páginas de detalle de producto (PDP), paneles de carrito y tablas de resumen de pago.
- Controles de Licencias y Asientos SaaS: Aprovisionar asientos de usuario, instancias de servidor o gigabytes de almacenamiento en páginas de precios o configuraciones de gestión de suscripciones.
- Entradas de Unidades Acotadas en Formularios: Capturar métricas restringidas como valores porcentuales (0–100%), límites de edad, dimensiones de artículos (largo/ancho/alto) o cantidades monetarias.
- Controles Financieros y de Calculadora: Seleccionar duraciones de préstamo, cantidades de depósito o incrementos de inversión en calculadoras interactivas.
- Controles de Panel y Filtros: Ajustar umbrales numéricos, límites de filas de paginación o filtros de rango de métricas en entornos de escritorio con alta densidad de datos.
Cuándo NO Usar
- Selección de Rango Continuo: Para exploración amplia y no específica de rangos numéricos donde los valores exactos son secundarios a las posiciones relativas, usar
accessible-range-slider-implementationo sliders de doble pulgar. - Números Grandes Arbitrarios: Para introducir números de tarjeta de crédito, teléfonos, códigos postales o números de seguridad social donde las operaciones de incremento/decremento no tienen sentido, usar
<input type="text" inputmode="numeric">estándar conform-design-system. - Selección de Fecha y Hora: Para seleccionar días del calendario, meses u horas del reloj, usar
calendar-and-date-system. - Conjuntos Grandes de Opciones Discretas: Al seleccionar entre cantidades preconfiguradas (por ejemplo, 25, 50, 100, 500), usar
segmented-control-systemocustom-select-and-combobox-system.
Entradas
- Límites de Valor: Restricciones de mínimo (
min), máximo (max) e incremento (step). - Contexto y Densidad: Espacio de diseño disponible (fila de tabla compacta en línea vs. bloque de compra prominente en PDP).
- Formato y Unidad de Entrada: Unidad física o monetaria asociada (p. ej.,
$,%,items,kg,seats). - Modo de Interacción: Si se permite escritura manual directa o si el ajuste está restringido solo a botones de stepper.
- Tokens de Marca y Superficie: Tokens de paleta para color de fondo de superficie, bordes activos, estados deshabilitados, anillos de foco y glifos de iconos.
Salidas
- Especificación del Componente Stepper: Anatomía visual que define el Botón de Decremento, la Pantalla/Entrada Numérica, el Botón de Incremento y la Etiqueta de Unidad.
- Matriz de Límites y Estados: Tratamientos visuales para los estados Predeterminado, Hover, Foco, Deshabilitado (en límites Mín/Máx), Cargando y Error.
- Especificación de Diseño Espacial Responsivo: Dimensiones de zonas táctiles (mínimo 44x44px para táctil, 24x24px para escritorio compacto), espaciado y métricas de fuente en diferentes puntos de ruptura.
- Accesibilidad y Mapeo de Teclado: Atributos ARIA (
role="spinbutton",aria-valuenow,aria-valuemin,aria-valuemax), configuraciones de región activa y especificaciones de manejadores de atajos de teclado.
Flujo de Trabajo
1. Seleccionar la Variante de Stepper
Elige la variante estructural adecuada según el contexto y la intención de interacción:
- Stepper Horizontal Estándar (Segmentado de 3 Piezas): Botón de Decremento (
-) a la izquierda, entrada de texto central, Botón de Incremento (+) a la derecha. Mejor para PDP de comercio electrónico, artículos del carrito y contadores de asientos SaaS. - Stepper Compacto en Línea (Flechas Apiladas): Entrada de texto con microbotones apilados verticalmente en el lado final. Mejor para tablas de datos de escritorio de alta densidad, barras de herramientas y paneles laterales de configuración SaaS.
- Entrada con Unidad Fija: Campo de texto con una etiqueta de unidad de prefijo/sufijo fija (p. ej.,
$,USD,px,%) y botones de stepper opcionales. Mejor para entradas financieras y formularios de configuración del sistema. - Contador de Botón Independiente: Píldora totalmente cliqueable donde tocar abre un modal/popover en línea o se transforma en un stepper activo al recibir el foco.
2. Establecer Anatomía Visual y Reglas de Zonas Táctiles
Estructurar el componente usando parámetros geométricos claros:
- Dimensiones de Zonas Táctiles: Asegurar que todos los botones interactivos de incremento/decremento tengan un objetivo de impacto mínimo de 44x44px en interfaces móviles/táctiles (WCAG 2.5.5 / 2.5.8). En UIs de escritorio compactas, mantener al menos 24x24px con suficiente relleno de impacto.
- Tamaño del Campo de Entrada: Establecer el ancho dinámicamente usando unidades CSS
chbasadas en la longitud máxima esperada de dígitos (p. ej.,width: calc(3ch + 2rem)para cantidades de 2 dígitos). - Tipografía y Alineación: Centrar el valor numérico dentro del campo de entrada. Usar números monoespaciados tabulares (
font-variant-numeric: tabular-nums;) para evitar cambios de diseño durante transiciones rápidas de valor. - Agrupación Visual: Encerrar botones y entrada dentro de un contenedor de borde compartido o píldora segmentada contigua para señalar funcionalidad unificada.
3. Definir Comportamientos de Límite y Estados Deshabilitados
Comunicar los límites mínimo y máximo claramente para evitar la frustración del usuario:
- En el Límite Mínimo (
value <= min):- Deshabilitar el botón de Decremento (atributo
disabledyaria-disabled="true"). - Aplicar estilo deshabilitado de bajo contraste (p. ej.,
opacity: 0.4; cursor: not-allowed;). - Si
min === 1en un contexto de carrito de comercio electrónico, opcionalmente transformar el botón de Decremento en un icono de "Papelera / Eliminar" cuando el valor sea 1 para permitir la eliminación del artículo de la línea.
- Deshabilitar el botón de Decremento (atributo
- En el Límite Máximo (
value >= max):- Deshabilitar el botón de Incremento (atributo
disabledyaria-disabled="true"). - Proporcionar texto de ayuda en línea (p. ej., "Máximo 10 artículos por pedido") o un tooltip sutil si el usuario intenta incrementar más.
- Deshabilitar el botón de Incremento (atributo
- Validación de Entrada Directa:
- Al perder el foco (
blur), fijar automáticamente las entradas escritas fuera de los límites al valor válido más cercano (p. ej., escribir99en un campo con máximo 10 se fija a10). - Si el incremento (
step) no es entero (p. ej.,step="0.5"), redondear los valores escritos al incremento válido más cercano al perder el foco.
- Al perder el foco (
4. Implementar Navegación por Teclado y Retroalimentación Táctil
Asegurar un control fluido en todos los dispositivos de entrada:
- Enlaces de Teclas:
FlechaArriba/FlechaDerecha: Incrementar valor porstep.FlechaAbajo/FlechaIzquierda: Decrementar valor porstep.RePág: Incrementar valor porstep * 10(o un delta de paso mayor).AvPág: Decrementar valor porstep * 10.Inicio: Establecer valor amin(si está definido).Fin: Establecer valor amax(si está definido).
- Repetición Automática al Mantener Presionado: Cuando el usuario mantiene presionado un botón de incremento/decremento (mediante puntero o teclado), iniciar la repetición automática del valor después de un retraso inicial de 500 ms, ciclando cada 100 ms.
- Teclado Táctil / Móvil: Establecer
inputmode="numeric"oinputmode="decimal"ypattern="[0-9]*"en el elemento<input>para activar el teclado numérico en dispositivos móviles sin forzar los spinners nativos del navegador.
5. Configurar Accesibilidad y Semántica para Lectores de Pantalla
Ofrecer una experiencia compatible con WCAG 2.1 / 2.2 AA:
- Opciones HTML Semánticas:
- Opción A (Entrada Nativa con Botones Stepper): Usar
<input type="text" inputmode="numeric">asociado con una<label>explícita. Acentuar los botones de decremento/incremento con<button type="button" aria-label="Disminuir cantidad">yaria-controls="input-id". - Opción B (Rol ARIA Spinbutton): Aplicar
role="spinbutton",aria-valuenow="3",aria-valuemin="1",aria-valuemax="10",aria-valuetext="3 asientos"yaria-label="Seleccionar número de asientos"al contenedor o entrada.
- Opción A (Entrada Nativa con Botones Stepper): Usar
- Gestión del Anillo de Foco: Mantener anillos de foco visibles y de alto contraste (
outline: 2px solid var(--focus-ring); outline-offset: 2px;) alrededor de botones activos y entradas de texto. Los anillos de foco nunca deben ocultarse o recortarse por los límites del contenedor padre. - Anuncios de Región Activa: Usar
aria-live="polite"o actualizararia-valuenowdinámicamente para que las tecnologías de asistencia anuncien inmediatamente los cambios de valor al presionar un botón.
Reglas de Decisión
Matriz de Patrones de Componentes
| Caso de Uso | Variante Recomendada | Ubicación del Botón | Estrategia Mín/Máx |
|---|---|---|---|
| PDP de Comercio Electrónico | Horizontal Estándar | Laterales (- Izquierda, + Derecha) | Mín = 1 (o Papelera en 1), Máx = Límite de stock |
| Artículo de Línea de Carrito | Horizontal Compacto / Híbrido Papelera | Laterales (-/Papelera Izquierda, + Derecha) | Mín = 0 (elimina artículo), Máx = Stock disponible |
| Asientos de Facturación SaaS | Horizontal con Sufijo de Unidad | Laterales (- Izquierda, + Derecha) | Mín = Nivel mínimo del plan, Máx = Límite de cuenta |
| Tabla de Datos de Escritorio | Stepper Apilado en Línea | Apilado al Final (▲ Arriba, ▼ Abajo) | Mín/Máx fijados al perder el foco |
| Cantidad Financiera | Entrada con Unidad Fija ($) | Laterales Opcionales o Solo Manual | Mín = 0, Máx = Límite con mensaje de validación |
Regla de Escritura Directa vs. Solo Botones
- Permitir Escritura Directa (Por Defecto): Para cantidades > 5 o cuando los usuarios puedan introducir números grandes directamente (p. ej., pedir 50 artículos o establecer un presupuesto de $500).
- Restringir Solo a Botones (entrada
readonly): Solo cuando el rango de valores es extremadamente pequeño (p. ej., 1 a 5) y la escritura de texto libre introduce una sobrecarga de validación innecesaria en dispositivos táctiles pequeños.
Restricciones
- Accesibilidad (WCAG 2.1 / 2.2 AA):
- Los botones deben proporcionar un atributo
aria-labelexplícito que describa la acción (p. ej., "Disminuir cantidad de artículo"). - Los botones de incremento y decremento deben mantener un objetivo de impacto mínimo de 44x44px en viewports táctiles (SC 2.5.8).
- Los indicadores de foco activos deben cumplir con WCAG 2.4.11 (Foco No Oscurecido) y SC 2.4.13 (Apariencia del Foco).
- Los botones deben proporcionar un atributo
- Formato de Números:
- Nunca permitir que valores en blanco o
NaNpermanezcan en la entrada al perder el foco. Recurrir amino al valor válido anterior. - Los números deben renderizarse usando
font-variant-numeric: tabular-nums;para evitar el reflujo del diseño durante los incrementos.
- Nunca permitir que valores en blanco o
- Teclados Blandos Móviles:
- Siempre establecer
inputmode="numeric"(odecimal) para abrir el teclado numérico estándar en iOS/Android. Evitar el estilo de flecha predeterminado del<input type="number">nativo deshabilitando los spinners nativos en CSS (::-webkit-inner-spin-button).
- Siempre establecer
Patrones de Falla Comunes
- Zonas Táctiles Pequeñas No Estándar: Usar botones de cheurón de 18x18px en móvil, causando toques incorrectos y frustración del usuario.
- Depender del
<input type="number">Nativo del Navegador: Permitir que los spinners predeterminados del navegador se rendericen de forma inconsistente, se superpongan al relleno de texto personalizado o provoquen ajustes de desplazamiento no deseados. - Falta de Indicaciones de Deshabilitación en Límites: Dejar el botón de Decremento visualmente activo cuando
value === min, llevando a los usuarios a hacer clic sin retroalimentación. - Entrada Libre No Acotada: Permitir que los usuarios escriban valores no válidos (p. ej.,
-5o999999) sin acotación o retroalimentación de error al perder el foco. - Falta de Soporte de Teclado: Diseñar botones
<div>personalizados que carecen de capacidad de foco conTaby manejo de eventos deFlechaArriba/FlechaAbajo.
Criterios de Validación
- Los botones de decremento e incremento cumplen con el objetivo de impacto mínimo de 44x44px en viewports táctiles.
- Se usa tipografía monoespaciada tabular (
tabular-nums) para evitar saltos de diseño durante las actualizaciones. - En los límites mínimo y máximo, los botones respectivos pasan a estados deshabilitados (
aria-disabled="true"). - La entrada móvil utiliza
inputmode="numeric"oinputmode="decimal". - El componente maneja correctamente las teclas
FlechaArriba,FlechaAbajo,RePág,AvPág,InicioyFin. - Se configuran etiquetas programáticas (
aria-labelo<label>) y roles ARIA (role="spinbutton"o botones explícitosaria-controls). - Los valores escritos fuera de los límites se fijan automáticamente o activan mensajes de error de validación al perder el foco (
blur). - Los indicadores de foco de alto contraste son visibles y no están oscurecidos.