fix: aria-label no lápis de editar em metas, orçamento e investimentos (closes #128) - #144
fix: aria-label no lápis de editar em metas, orçamento e investimentos (closes #128)#144Guiroos wants to merge 2 commits into
Conversation
closes #128) Os três lápis de editar em GoalDialog, BudgetOverrideDialog e InvestmentEntryDialog envolvem só um ícone Pencil sem aria-label — o Icon do lucide-react@1.8.0 marca o svg como aria-hidden quando não recebe filho nem prop de a11y, então o botão chega ao leitor de tela como role=button name="". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012WLtBDDRT1KDQqQtNjTgjK
Guiroos
left a comment
There was a problem hiding this comment.
Revisão do head 14fda0e. A correção está certa e fecha a #128 por inteiro (exigência 8): os 3 sites — InvestmentEntryDialog.tsx:192 (ramo existing), BudgetOverrideDialog.tsx:130, GoalDialog.tsx:161 — estão rotulados, com os textos que a issue nomeou, no <Button> e não no <Pencil>. O {...props} de components/ui/button.tsx:80 repassa o atributo ao <button> real, então o nome chega mesmo à árvore. Nenhuma substituição silenciosa de abordagem na correção.
Rodei os gates nesta sessão, sobre este head: npm ci, npm run lint, npm run format:check, npm run typecheck e npm test verdes (35 arquivos, 534 testes).
Um achado, nit — sobre o alcance do gate, não sobre o fix. Detalhe, reprodução e correção verificada no comentário inline.
Sendo justo com a força dele: as duas correções erradas realistas são barradas, e eu mutei o fonte para checar em vez de deduzir. Fix revertido nos três arquivos → 3 testes vermelhos. aria-label no <Pencil> em vez do <Button> (a errada que a #128 nomeia) → vermelho nos três. Vale a mesma ressalva que ficou registrada na revisão do #139: essa segunda só é barrada porque a asserção exige o atributo sozinho numa linha e o printWidth: 100 do prettier mantém <Pencil className="h-3 w-3" aria-label="Editar orçamento" /> (64 colunas) numa linha só — conferido com prettier --check. A margem é estreita e não está sob gate nenhum.
Duas notas que não são achado:
1. Colisão de arquivo com o #140, não declarada aqui. O corpo diz que __tests__/unit/a11y-nomes-acessiveis.test.ts foi criado "porque a #126 ainda não foi mergeada", mas hoje são três PRs abertos criando este mesmo arquivo do zero: #139 (#126), #140 (#127) e este. O #140 registra a colisão na seção de risco e diz o que fazer (somar os describe, não descartar um lado); vale acrescentar a mesma linha aqui, porque quem mergear por último resolve o conflito sem esse aviso.
2. A lista de consumidores do site 2 na #128 está mais larga que a realidade — o que não muda o PR, só o impacto declarado. O gatilho do InvestmentEntryDialog só renderiza com !isControlled (:184-186). Dos três consumidores que a issue lista, InvestmentTypeCard.tsx:322 e dashboard/InvestmentList.tsx:60 passam open/onOpenChange e chegam pelo RowActions (kebab, já nomeado) — o lápis deste componente não é renderizado ali. Quem de fato recebe o rótulo é InvestmentTypeAccordion.tsx:297, que é uncontrolled. O site tem consumidor (exigência 7 satisfeita) e a correção continua certa; a superfície é uma, não três.
Generated by Claude Code
… ícone Achado no review de #144: expect(source).toMatch(/aria-label/) sobre o arquivo inteiro passava mesmo com o rótulo no botão errado ("Usar padrão"), porque o gatilho não é ramo de ternário e o arquivo tem dois outros <Button> fora dele. Verificado por mutação: reverter o rótulo do trigger e colocá-lo no botão de reset deixava o teste anterior verde; a nova captura (mais próximo do <Pencil>) falha corretamente. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012WLtBDDRT1KDQqQtNjTgjK
|
Respondendo à revisão de
Suíte completa após o ajuste: Generated by Claude Code |
O que mudou
Adicionado
aria-labelao botão de ícone (<Pencil>) de editar em três componentes:components/investimentos/InvestmentEntryDialog.tsx:187-195—aria-label="Editar registro"(ramoexistingdo ternário de três braços)components/configuracao-mes/BudgetOverrideDialog.tsx:125-133—aria-label="Editar orçamento"components/metas/GoalDialog.tsx:156-164—aria-label="Editar meta"(ramoelsedo ternáriomode === 'create')Mudança puramente aditiva, sem alteração visual ou de comportamento.
Por que dessa forma
lucide-react@1.8.0(pinado empackage.json:45) marca o<svg>do ícone comoaria-hidden="true"quando ele não recebe filho nem prop de a11y (hasA11yProp). Como o<Button size="icon">nesses três sites só tem oPencilcomo filho, orole=buttonchega ao leitor de tela sem nome nenhum (medido via CDP na auditoria original, #106). O rótulo foi colocado no<Button>(o controle clicável), não no ícone — consistente com os outros 20 controles do repo que já seguem esse padrão.Segui a proposta da issue #128 à risca (mesmos três arquivos, mesmos textos de rótulo), sem desvio de abordagem.
Como testei
npm run lint && npm run format:check && npm run typecheck && npm test— todos verdes (535/535 testes passando)npm run build— build de produção completo sem errosds-reviewerrodado nos três diffs isoladamente — aprovado sem violações (mudança é só a proparia-label, não toca tokens/classes/estrutura)npm run test:integrationnão foi executado (exige credenciais Neon e só roda em push paramain) — não se aplica de qualquer forma, pois a mudança não toca camada de dadosNovo arquivo de teste:
__tests__/unit/a11y-nomes-acessiveis.test.ts, criado porque a #126 (que criaria esse arquivo primeiro) ainda não foi mergeada. Cada asserção ancora no ramo/bloco JSX específico do botão-alvo — não emtoMatch(/aria-label/)genérico sobre o arquivo — porque os três componentes têm mais de um<Button>no mesmo trecho, e uma asserção solta passaria com qualquer um deles rotulado. Ajustado após review humano (ver thread resolvido): a asserção doBudgetOverrideDialoginicialmente rodava sobre o arquivo inteiro e não pegava rótulo no botão errado — corrigida para ancorar no<Button>mais próximo do íconePencil, verificado por mutação.Risco e o que NÃO foi coberto
Risco baixo: mudança aditiva de um atributo ARIA, sem impacto em lógica, estilo ou dados. Não cobre os outros 6 sites do achado original (#106) — esses já têm issues próprias: #126 (DS,
DeleteButton), #127 (lápis em/categoriase/contas), #129 (os dois "X" emSplitSection.tsx).Colisão de arquivo esperada.
__tests__/unit/a11y-nomes-acessiveis.test.tsestá sendo criado do zero por três PRs em paralelo — este, #139 (fatia de #126) e #140 (fatia de #127). Quem mergear por último resolve o conflito somando osdescribeblocks de cada PR, não descartando um lado.Arquivos tocados
components/investimentos/InvestmentEntryDialog.tsxcomponents/configuracao-mes/BudgetOverrideDialog.tsxcomponents/metas/GoalDialog.tsx__tests__/unit/a11y-nomes-acessiveis.test.ts(novo)🤖 Generated with Claude Code
https://claude.ai/code/session_012WLtBDDRT1KDQqQtNjTgjK