Sistema de Entrada Numérica e Stepper
Propósito
O Sistema de Entrada Numérica e Stepper fornece um framework padronizado para projetar, estruturar e implementar controles usados para selecionar, ajustar ou inserir valores numéricos discretos. A entrada numérica precisa — como quantidades de itens no carrinho, alocações de licenças SaaS, unidades de faixas de preço, faixas de orçamento ou especificações dimensionais — requer equilibrar microajustes rápidos com edição direta de texto, estados claros de limite mínimo/máximo, alvos de toque amigáveis e acessibilidade total para teclado e leitores de tela.
Os controles HTML padrão <input type="number"> renderizam de forma inconsistente entre navegadores, frequentemente apresentando setas nativas minúsculas e não customizáveis que violam as diretrizes de alvo de toque (WCAG 2.2 SC 2.5.8) e disparam ajustes acidentais por rolagem. Este skill define padrões explícitos de UI, regras de layout espacial, estados de interação e padrões de acessibilidade para steppers numéricos customizados e campos com unidade.
Casos de Uso
- Seletores de Quantidade em Carrinho de E-Commerce: Permitir que compradores aumentem, diminuam ou digitem facilmente quantidades de produtos em PDPs, gavetas de carrinho e tabelas de resumo de checkout.
- Controles de Licenças e Assentos em Planos SaaS: Provisionar assentos de usuário, instâncias de servidor ou gigabytes de armazenamento em páginas de preços ou configurações de gerenciamento de assinatura.
- Entradas de Unidade Limitadas em Formulários: Capturar métricas restritas como valores percentuais (0–100%), limites de idade, dimensões de itens (comprimento/largura/altura) ou valores monetários.
- Controles Financeiros e de Calculadora: Selecionar prazos de empréstimo, valores de depósito ou incrementos de investimento em calculadoras interativas.
- Controles de Dashboard e Filtros: Ajustar limites numéricos, limites de linhas de paginação ou filtros de faixa métrica em ambientes desktop densos em dados.
Quando NÃO Usar
- Seleção de Faixa Contínua: Para exploração de faixa numérica ampla e não específica onde valores exatos são secundários a posições relativas, use
implementacao-de-slider-de-faixa-acessivelou sliders de dois polegares. - Números Grandes Arbitrários: Para inserir números de cartão de crédito, telefone, CEP ou CPF, onde operações de incremento/decremento não fazem sentido, use
<input type="text" inputmode="numeric">padrão comsistema-de-design-de-formularios. - Seleção de Data e Hora: Para selecionar dias do calendário, meses ou horários, use
sistema-de-calendario-e-data. - Conjuntos Grandes de Opções Discretas: Ao selecionar entre quantidades em massa pré-configuradas (por exemplo, 25, 50, 100, 500), use
sistema-de-controle-segmentadoousistema-de-select-e-combobox-customizado.
Entradas
- Limites de Valor: Restrições de mínimo (
min), máximo (max) e incremento de passo (step). - Contexto e Densidade: Espaço de layout disponível (linha de tabela inline compacta vs. bloco de compra PDP proeminente).
- Formato e Unidade de Entrada: Unidade física ou monetária associada (por exemplo,
$,%,itens,kg,assentos). - Modo de Interação: Se a digitação manual direta é permitida ou se o ajuste é restrito apenas aos botões do stepper.
- Tokens de Marca e Superfície: Tokens de paleta para cor de fundo da superfície, bordas ativas, estados desabilitados, anéis de foco e glifos de ícone.
Saídas
- Especificação do Componente Stepper: Anatomia visual definindo o Botão de Decremento, Exibição/Entrada Numérica, Botão de Incremento e Rótulo de Unidade.
- Matriz de Limite e Estado: Tratamentos visuais para estados Padrão, Hover, Foco, Desabilitado (nos limites Mín/Máx), Carregando e Erro.
- Especificação de Layout Espacial Responsivo: Dimensões do alvo de toque (mínimo 44x44px para toque, 24x24px para desktop compacto), espaçamento e métricas de fonte entre breakpoints.
- Mapeamento de Acessibilidade e Teclado: Atributos ARIA (
role="spinbutton",aria-valuenow,aria-valuemin,aria-valuemax), configurações de região ativa e especificações de manipuladores de atalhos de teclado.
Fluxo de Trabalho
1. Selecionar a Variante do Stepper
Escolha a variante estrutural apropriada com base no contexto e na intenção de interação:
- Stepper Horizontal Padrão (Segmentado em 3 Partes): Botão Decrementar (
-) à esquerda, entrada de texto central, botão Incrementar (+) à direita. Melhor para PDPs de e-commerce, itens de carrinho e contadores de assentos SaaS. - Stepper Inline Compacto (Setas Empilhadas): Entrada de texto com micro-botões empilhados verticalmente no lado direito. Melhor para tabelas de dados desktop de alta densidade, barras de ferramentas e painéis laterais de configurações SaaS.
- Entrada com Unidade Fixa: Campo de texto com um rótulo de unidade prefixo/sufixo fixo (por exemplo,
$,USD,px,%) e botões de stepper opcionais. Melhor para entradas financeiras e formulários de configuração de sistema. - Contador de Botão Independente: Pílula totalmente clicável onde tocar abre um modal/popover inline ou se transforma em um stepper ativo ao receber foco.
2. Estabelecer Anatomia Visual e Regras de Alvo de Toque
Estruture o componente usando parâmetros geométricos claros:
- Dimensões do Alvo de Toque: Garanta que todos os botões interativos de incremento/decremento tenham um alvo de clique mínimo de 44x44px em interfaces móveis/táteis (WCAG 2.5.5 / 2.5.8). Em UIs compactas apenas para desktop, mantenha pelo menos 24x24px com preenchimento de clique adequado.
- Dimensionamento do Campo de Entrada: Defina a largura dinamicamente usando unidades CSS
chcom base no comprimento máximo esperado de dígitos (por exemplo,width: calc(3ch + 2rem);para quantidades de 2 dígitos). - Tipografia e Alinhamento: Alinhe o valor numérico ao centro dentro do campo de entrada. Use números monoespaçados tabulares (
font-variant-numeric: tabular-nums;) para evitar mudanças de layout durante transições rápidas de valor. - Agrupamento Visual: Envolva botões e entrada em um contêiner de borda compartilhada ou pílula segmentada contígua para sinalizar funcionalidade unificada.
3. Definir Comportamentos de Limite e Estados Desabilitados
Comunique os limites mínimo e máximo claramente para evitar frustração do usuário:
- No Limite Mínimo (
valor <= min):- Desabilite o botão Decrementar (atributo
disabledearia-disabled="true"). - Aplique estilização de desabilitado com baixo contraste (por exemplo,
opacity: 0.4; cursor: not-allowed;). - Se
min === 1em um contexto de carrinho de e-commerce, opcionalmente transforme o botão Decrementar em um ícone "Lixeira / Excluir" quando o valor for 1 para permitir a remoção do item da linha.
- Desabilite o botão Decrementar (atributo
- No Limite Máximo (
valor >= max):- Desabilite o botão Incrementar (atributo
disabledearia-disabled="true"). - Forneça texto de ajuda inline (por exemplo, "Máximo de 10 itens por pedido") ou uma dica de ferramenta sutil se o usuário tentar incrementar ainda mais.
- Desabilite o botão Incrementar (atributo
- Validação de Entrada Direta:
- No
blurda entrada, force automaticamente as entradas digitadas fora dos limites para o limite válido mais próximo (por exemplo, digitar99em um campo com máximo 10 é ajustado para10). - Se o incremento de passo não for inteiro (por exemplo,
step="0.5"), arredonde os valores digitados para o incremento de passo válido mais próximo noblur.
- No
4. Implementar Navegação por Teclado e Feedback de Toque
Garanta controle contínuo em todos os dispositivos de entrada:
- Atalhos de Teclado:
ArrowUp/ArrowRight: Incrementar valor porstep.ArrowDown/ArrowLeft: Decrementar valor porstep.PageUp: Incrementar valor porstep * 10(ou delta de passo maior).PageDown: Decrementar valor porstep * 10.Home: Definir valor paramin(se definido).End: Definir valor paramax(se definido).
- Repetição Automática ao Pressionar e Segurar: Quando o usuário mantiver pressionado um botão de incremento/decremento (via ponteiro ou teclado), inicie a repetição automática do valor após um atraso inicial de 500ms, ciclando a cada 100ms.
- Teclado Tátil / Móvel: Defina
inputmode="numeric"ouinputmode="decimal"epattern="[0-9]*"no elemento<input>para acionar o teclado numérico em dispositivos móveis sem forçar as setas nativas padrão do navegador.
5. Configurar Acessibilidade e Semântica para Leitores de Tela
Entregue uma experiência compatível com WCAG 2.1 / 2.2 AA:
- Opções de HTML Semântico:
- Opção A (Entrada Nativa com Botões Stepper): Use
<input type="text" inputmode="numeric">associado a um<label>explícito. Acompanhe os botões de decremento/incremento com<button type="button" aria-label="Diminuir quantidade">earia-controls="id-da-entrada". - Opção B (Papel ARIA Spinbutton): Aplique
role="spinbutton",aria-valuenow="3",aria-valuemin="1",aria-valuemax="10",aria-valuetext="3 assentos"earia-label="Selecione o número de assentos"ao contêiner ou entrada.
- Opção A (Entrada Nativa com Botões Stepper): Use
- Gerenciamento do Anel de Foco: Mantenha anéis de foco visíveis e de alto contraste (
outline: 2px solid var(--focus-ring); outline-offset: 2px;) ao redor de botões ativos e entradas de texto. Os anéis de foco nunca devem ser ocultados ou cortados pelos limites do contêiner pai. - Anúncios de Região Ativa: Use
aria-live="polite"ou atualizearia-valuenowdinamicamente para que as tecnologias assistivas anunciem imediatamente as mudanças de valor ao pressionar um botão.
Regras de Decisão
Matriz de Padrões de Componente
| Caso de Uso | Variante Recomendada | Posição dos Botões | Estratégia Mín/Máx |
|---|---|---|---|
| PDP de E-Commerce | Horizontal Padrão | Laterais (- Esquerda, + Direita) | Mín = 1 (ou Lixeira em 1), Máx = Limite de estoque |
| Item de Linha do Carrinho | Horizontal Compacto / Híbrido com Lixeira | Laterais (-/Lixeira Esquerda, + Direita) | Mín = 0 (remove item), Máx = Estoque disponível |
| Assentos de Faturamento SaaS | Horizontal com Sufixo de Unidade | Laterais (- Esquerda, + Direita) | Mín = Nível mínimo do plano, Máx = Limite da conta |
| Tabela de Dados Desktop | Stepper Inline Empilhado | Empilhado no Lado Direito (▲ Topo, ▼ Base) | Mín/Máx corrigidos no blur |
| Valor Financeiro | Entrada com Unidade Fixa ($) | Laterais Opcionais ou Somente Manual | Mín = 0, Máx = Limite com mensagem de validação |
Regra de Digitação Direta vs. Somente Botões
- Permitir Digitação Direta (Padrão): Para quantidades > 5 ou onde os usuários podem inserir números grandes diretamente (por exemplo, pedir 50 itens ou definir um orçamento de $500).
- Restringir a Botões Apenas (entrada
readonly): Somente quando o intervalo de valores for extremamente pequeno (por exemplo, 1 a 5) e a digitação de texto livre introduzir sobrecarga de validação desnecessária em dispositivos de toque pequenos.
Restrições
- Acessibilidade (WCAG 2.1 / 2.2 AA):
- Os botões devem fornecer um atributo
aria-labelexplícito descrevendo a ação (por exemplo, "Diminuir quantidade do item"). - Os botões de incremento e decremento devem manter um alvo de toque mínimo de 44x44px em viewports de toque (SC 2.5.8).
- Os indicadores de foco ativos devem atender aos critérios WCAG 2.4.11 (Foco Não Obscurecido) e SC 2.4.13 (Aparência do Foco).
- Os botões devem fornecer um atributo
- Formatação de Números:
- Nunca permita que valores em branco ou
NaNpermaneçam na entrada no blur. Reverta paraminou o valor válido anterior. - Os números devem ser renderizados usando
font-variant-numeric: tabular-nums;para evitar refluxo de layout durante incrementos.
- Nunca permita que valores em branco ou
- Teclados Virtuais Móveis:
- Sempre defina
inputmode="numeric"(oudecimal) para abrir o teclado numérico padrão no iOS/Android. Evite a estilização de seta padrão do<input type="number">nativo desabilitando as setas nativas no CSS (::-webkit-inner-spin-button).
- Sempre defina
Padrões de Falha Comuns
- Alvos de Toque Minúsculos e Não Padronizados: Usar botões de chevron de 18x18px no celular, causando toques errados e frustração do usuário.
- Dependência do
<input type="number">Nativo do Navegador: Permitir que as setas padrão do navegador renderizem de forma inconsistente, sobreponham o preenchimento de texto customizado ou disparem ajustes de rolagem não intencionais. - Falta de Sinais Visuais de Desabilitação nos Limites: Deixar o botão Decrementar visualmente ativo quando
valor === min, levando os usuários a clicar sem feedback. - Entrada Livre Não Corrigida: Permitir que os usuários digitem valores inválidos (por exemplo,
-5ou999999) sem corrigir ou fornecer feedback de erro no blur. - Falta de Suporte a Teclado: Projetar botões
<div>customizados que não têm capacidade de foco porTabe tratamento de eventosArrowUp/ArrowDown.
Critérios de Validação
- Os botões de decremento e incremento atendem ao alvo de toque mínimo de 44x44px em viewports de toque.
- A tipografia monoespaçada tabular (
tabular-nums) é usada para evitar oscilações de layout durante atualizações. - Nos limites mínimo e máximo, os respectivos botões transitam para estados desabilitados (
aria-disabled="true"). - A entrada móvel utiliza
inputmode="numeric"ouinputmode="decimal". - O componente lida corretamente com as teclas
ArrowUp,ArrowDown,PageUp,PageDown,HomeeEnd. - Rótulos programáticos (
aria-labelou<label>) e papéis ARIA (role="spinbutton"ou botõesaria-controlsexplícitos) estão configurados. - Valores digitados fora dos limites são corrigidos automaticamente ou disparam mensagens de erro de validação no
blur. - Indicadores de foco de alto contraste estão visíveis e não obscurecidos.