Skip to content

UX/Feel: erro de digitação é invisível onde o olho está (feedback de erro no card do editor · §779) #10

Description

@caioross

Contexto

Feedback da persona O Iniciante (discussion #9, fricção nº2, jogado em produção): ao digitar funz no lugar de func, nada fica vermelho onde o olho está. O jogador ficou "por que travei? qual tecla errei?". O único sinal foi numérico e distante (ERROS: 1 / PRECISÃO: 75%).

Diagnóstico técnico (a red já existe, mas no lugar errado para o olhar):

  • O painel do código (CodeDisplay.tsx) pinta o char errado de vermelho: isError = done && typed[i] !== ch → classe char-error (CodeDisplay.tsx:64).
  • Mas o jogador olha para o editor onde digita — a textarea de CodeEditor.tsx, que é um campo de texto puro e não colore caractere nenhum. Zero feedback de erro no ponto de fixação do olhar.
  • Race.tsx já sabe, a cada tecla, quantos chars novos vieram errados (Race.tsx:83-88, newErrors) — o sinal para disparar o feedback já existe, só não é usado visualmente.

Isto é exatamente a Parte IV · Spec — erro (docs/UI-AAA-OVERHAUL.md:779): o card do editor treme 4–6px por 80ms no erro, comunicando "erro aqui", + fallback de reduced-motion.

Escopo (1 fatia)

Feedback de erro no card do editor, dirigido pelo sinal de "última tecla foi errada" já computado em handleInput:

  • Erro → screen-shake cirúrgico só no card do editor (não a tela toda): transform na GPU, 4–6px, ~80ms, ease-out decaindo.
  • prefers-reduced-motion → sem movimento: flash de cor (borda/fundo do card pisca vermelho brevemente) + ícone de erro na margem. Nunca pisca > 3Hz.
  • Erro nunca comunicado só por cor: cor + posição (o shake/margem) — mantendo o char-error do painel de código.

Fora de escopo (não fazer aqui): type.error (som) depende de lib/sound.ts que ainda não existe (§IV.1 🔴); háptico navigator.vibrate pode entrar se trivial, mas é opcional. Combo (§IV.4) é outra issue.

Critérios de aceitação (verificáveis)

  • Digitar um caractere errado durante a corrida produz feedback visível no card do editor (não só no painel de código).
  • Com prefers-reduced-motion: reduce ativo, não há movimento — o feedback é flash de cor + ícone, e nada pisca acima de 3Hz.
  • O shake usa transform (composited); não introduz layout/reflow nem trabalho pesado competindo com a textarea (área sagrada: latência de input a 60fps — CLAUDE.md).
  • pnpm typecheck + pnpm build verdes; node scripts/validate-metrics.mjs verde (não altera cálculo de WPM/erros).
  • O char-error existente em CodeDisplay.tsx continua funcionando (sem regressão).

Dica de abordagem

handleInput (Race.tsx:74) já detecta newErrors > 0 no bloco de teclas novas — emita daí um "pulso de erro" (ex.: errorPulse timestamp em state, ou um contador) e passe ao CodeEditor, que aplica a classe de shake/flash com key/timeout curto para reprisar em erros consecutivos. Springs/durações da §I (motion tokens) quando aplicável. Testar em produção-like: erro simples, erros consecutivos, e com reduced-motion no DevTools.

Origem: feedback da persona em #9. Referência de spec: docs/UI-AAA-OVERHAUL.md §779 (Parte IV).

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Alto valor — próximo da filaarea:engineMotor de digitação, WPM, precisão, anti-cheatarea:uiInterface, design system, animação, game feel

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions