Componentes
54. Botão dividido
seed-componentes.md v1.43 · §54seção 60 de 9854-botao-dividido-estavel-f7-3-2026-08-16-bd1-bd9.md · MD5 078c2a6aTítulo completo no canon: Botão dividido — estável (F7.3, 2026-08-16) · BD1–BD9 + MN9 · fecha a dívida A-P1
Como esta seção nasceu tarde, e por que isso está escrito. O botão dividido foi produzido em 2026-08-15 como artefato — os códigos
BD1–BD6eMN9viviam só no comentário de CSS dobanco-navegacao.html, e nenhum arquivo canônico os mencionava. Foi o inverso exato da ordem que este projeto pratica desde o marco v1.2: decisão escrita → artefato produzido. A leitura de volta da edição v8.4 do MANIFESTO mediu a lacuna (zero ocorrências deBD1em qualquer.md) e abriu a dívida A-P1. Ela fecha aqui, e fecha pelo caminho certo: rito completo de três rodadas, e não transcrição do comentário — reconstruir spec a partir do artefato é reconstrução de memória, que este projeto já pagou caro na v7.0. Decisão do Rafael em 2026-08-16: "pode resolver logo de uma vez, vamos evitar jogar as coisas pra frente."Base (3 rodadas encadeadas, 2026-08-16). R1 canon — o que o padrão É. A definição é estável e antiga: um botão com dois componentes, rótulo e seta, em que clicar no rótulo dispara a ação padrão e clicar na seta abre a lista das demais; é um híbrido entre botão e menu, que agrupa comandos relacionados e ainda oferece acesso de um clique à escolha padrão. A NN/g é explícita sobre o requisito visual: a seta que sinaliza o menu precisa estar claramente separada do rótulo — sem essa separação o padrão não é reconhecido. Vários sistemas convergem em três regras de uso: as ações do menu têm de pertencer ao mesmo fluxo da ação padrão; a variante destrutiva não existe para o botão dividido, e uma ação destrutiva, se houver, aparece uma só vez e sempre por último no menu; e quando não há ação dominante, o certo é um botão de menu simples, não um dividido — sem ação dominante não há padrão que valha proteger. R2 mercado/stack — o que o padrão FAZ no teclado. O comportamento é o do menu button do WAI-ARIA, e é o mesmo em React Aria, Radix e nos sistemas de referência: o gatilho leva
aria-haspopup,aria-expandedearia-controls; Seta ↓, Espaço ou Enter abrem o menu e movem o foco para o PRIMEIRO item; Seta ↑ abre e vai para o ÚLTIMO; dentro do menu as setas circulam, Home e End vão às pontas, letras navegam por inicial; Esc fecha e devolve o foco ao gatilho. Com o menu aberto, o gatilho não recebe foco enquanto o usuário percorre os itens. R3 normas e fora do circuito — onde o padrão FALHA. A crítica prática é dura e entrou como contrato: o botão dividido não é recomendado para toque, pelo problema do dedo grosso, e mesmo no desktop as duas zonas precisam atender ao tamanho mínimo de alvo. E há uma exigência de aprendizado: o padrão só funciona em aplicação de uso repetido; em fluxo de uma vez só, o usuário não percebe o menu secundário.
54.1 Os contratos#
| # | Contrato | O que ele descarta, e por quê |
|---|---|---|
| BD1 | DOIS BOTÕES NATIVOS lado a lado, dentro de um contêiner que dá a aparência de peça única | Um botão só com duas zonas de clique. Um clique que faz coisas diferentes conforme ONDE caiu é o oposto de um alvo previsível, e o leitor de tela não teria como anunciar as duas ações — há um nome acessível por elemento |
| BD2 | O fio separador é border-left do segundo botão, nunca pseudo-elemento nem sombra |
background e box-shadow são descartados em forced-colors, e ali o fio sumiria — junto com a única pista de que existem duas ações. Borda sobrevive |
| BD3 | O gatilho tem min-width:44px: é alvo próprio, não apêndice do botão principal |
Largura por conteúdo. Com 36px ele mediu 37 × 44 e reprovou o R4 da suite-render. O eixo curto de um alvo pode ser qualquer um dos dois — lição que o stepper já tinha dado na mesma fase, e que se repetiu quatro vezes |
| BD4 | O gatilho é menu button: aria-haspopup="menu", aria-expanded alternando, aria-controls apontando para o menu |
aria-expanded sozinho: sem aria-haspopup a tecnologia assistiva não identifica o elemento como abridor de menu |
| BD5 | Teclado do WAI-ARIA, inteiro: ↓/Espaço/Enter abrem e focam o primeiro item; ↑ abre e foca o último; setas circulam; Home/End vão às pontas; Esc fecha e devolve o foco ao gatilho | Implementar só o clique. Metade do padrão de teclado é pior que nenhum: cria expectativa e frustra |
| BD6 | A ação do corpo é a MAIS FREQUENTE do conjunto, e as do menu pertencem ao mesmo fluxo | Usar o dividido quando não há ação dominante — aí o certo é botão de menu simples. Sem dominante não há padrão a proteger |
| BD7 | O gatilho NUNCA executa ação — ele só abre e fecha o menu | Gatilho que dispara a ação padrão e abre o menu: torna o resultado do clique imprevisível |
| BD8 | Sem variante destrutiva. Uma ação destrutiva, se existir, aparece uma vez no menu e por último | Agrupar duas ações destrutivas atrás de um gatilho de 44px |
| BD9 | Em contexto de TOQUE e no degrau estreito, o botão dividido COLAPSA: vira botão de menu único, com a ação padrão como primeiro item | Manter as duas zonas no toque. A norma do alvo continua cumprida, mas duas zonas coladas de 44px convidam ao erro — e o padrão pressupõe uso repetido, que o toque casual não tem |
| MN9 | Cabeçalho de seção do menu com ação secundária à direita. O rótulo nomeia o grupo por aria-labelledby; a ação é <button> de verdade e fica FORA da varredura de menuitem |
Tratar a ação como opção da lista. Ela não é uma escolha do menu — é atalho para gerenciar a lista, e virar menuitem faria a contagem de opções mentir |
54.2 Anatomia#
┌──────────────────────┬─────┐
│ Criar ordem │ ▾ │ ← BD1: dois <button> reais
└──────────────────────┴─────┘
ação padrão (BD6) │ └ min-width 44px (BD3)
└── border-left 1px (BD2)
A anatomia com BORDA foi decidida no gate de 2026-08-15: a proposta alternativa (botão sem contorno) foi medida, apresentada em amostra A/B e reprovada. Verbatim do Rafael: "esse da foto que mandei está melhor". Não reabrir sem pedido dele.
54.3 Estados e tokens#
| Estado | Tratamento |
|---|---|
| Repouso | fundo action-primary, tinta text-on-brand, raio 8 nas pontas externas |
| Hover | escurecimento por sobreposição, aplicado a cada metade em separado — o hover diz qual metade receberá o clique |
| Foco | anel border-focus com outline-offset:2px e z-index:1, para o anel não ser cortado pela metade vizinha |
| Menu aberto | aria-expanded="true", e o caret gira 180° |
| Desabilitado | aria-disabled nas duas metades; nunca só numa |
54.4 Validação#
| Guarda | O que prova |
|---|---|
suite-navegacao.mjs |
presença estrutural, ARIA do gatilho e a regra do MN9 fora da varredura de menuitem |
render-* R4 |
as duas metades com 44px nos dois eixos — foi esta guarda que reprovou o gatilho a 37 × 44 |
| Escala de cinza do preview | o fio sobrevive sem cor; é ele que diz que há duas ações |
54.5 Pendências#
| # | Pendência | Por que fica aberta |
|---|---|---|
| BD-P1 | O colapso do BD9 está escrito e não tem gabarito | Nenhuma tela do projeto usa botão dividido ainda; o colapso nasce junto com o primeiro uso real, medido |
| BD-P2 | Navegação por letra inicial dentro do menu (parte do BD5) não é exercitada na bancada | A bancada tem três itens curtos; a navegação por inicial só é observável com lista maior |
Também cita o §54: banco-navegacao, tela-detalhe.