Files
amare/openspec/changes/enhance-public-motion/design.md

4.6 KiB
Raw Blame History

Context

O site público usa Blade/Tailwind e já contém um runtime pequeno em resources/js/motion.js: abertura focal da home, page-open, reveals com IntersectionObserver e progresso do índice. A cobertura e a marcação são parciais, os reveals não têm grupos/direções explícitas e a matriz browser se concentra nas quatro páginas visuais originais. A mudança cruza templates, CSS, JavaScript e testes, mas não envolve estado de aplicação, dados ou dependências.

Goals / Non-Goals

Goals:

  • Tornar a coreografia Heritage Editorial consistente em toda página pública visual.
  • Manter texto legível durante toda entrada, animando somente transform e recorte de mídia.
  • Garantir enhancement progressivo: estado final imediato sem JavaScript, observer ou com movimento reduzido.
  • Preservar interação, foco, validação e ausência de overflow em desktop/mobile.
  • Cobrir marcação, comportamento real, acessibilidade e console.

Non-Goals:

  • Não criar transições de rota, parallax, animação contínua ou repetição ao voltar no scroll.
  • Não mudar copy, dados de clientes, estrutura de layout, CMS, controllers, banco, APIs ou Filament.
  • Não adicionar biblioteca de animação nem itens de SPEC.md §4.2.

Decisions

  1. Contrato declarativo em atributos data-*. Templates usarão data-motion="page-open", data-motion-beat, data-reveal-group, data-reveal e data-reveal-from="up|left|right". CSS define o estado visual e JS apenas ativa classes. Alternativa rejeitada: acoplar seletores a classes de layout, por tornar a coreografia frágil a ajustes visuais.

  2. Enhancement opt-in pelo elemento raiz. O HTML inicial permanece no estado final; o runtime adiciona html[data-motion="enhance"] somente quando movimento é permitido e os recursos necessários existem. Sem JS, sem IntersectionObserver, ou em reduce, o atributo não é aplicado/removido e todo conteúdo fica final. Alternativa rejeitada: estado inicial oculto no HTML/CSS, pois pode prender conteúdo fora da tela.

  3. Transformação sem fade de texto. Entradas duram cerca de 500 ms com cubic-bezier(0.16, 1, 0.3, 1), deslocamento vertical de 12 px e lateral de 24 px no desktop/16 px no mobile. Grupos recebem stagger de 90 ms limitado a 270 ms. Mídia pode combinar transform com clip-path; texto não usa opacidade. Alternativa rejeitada: fade geral, que reduz contraste durante axe e legibilidade percebida.

  4. Observer de execução única. Cada reveal intersectado recebe o estado final e é removido do observer. Grupos calculam índice limitado para o delay; depoimentos definem explicitamente left/right pela coluna, preservando alternância no mobile. Alternativa rejeitada: reanimar em toda rolagem, por criar fadiga e instabilidade.

  5. Feedback separado das entradas. CTAs, links, navegação e controles recebem transições curtas (100200 ms) em cor/transform/borda. :focus-visible continua prioritário; alertas e mensagens de erro não entram no contrato de motion. Alternativa rejeitada: feedback via JS, desnecessário para estados CSS.

  6. Progresso com coalescência por frame. Eventos de scroll apenas agendam uma atualização por requestAnimationFrame; o cálculo existente é preservado. Alternativa rejeitada: calcular em todo evento, que multiplica leituras/escritas durante scroll.

  7. Testes em camadas. Feature tests comprovam contratos Blade/CSS/JS e renderização de erros; browser tests comprovam entrada, stagger, direções, reduced motion, fallback, interação, overflow e console. Axe e console incluem sobre, contato, privacidade e 404; demais erros ficam em renderização feature.

Risks / Trade-offs

  • [Conteúdo pisca entre estado final e início do enhancement] → inicializar no primeiro módulo Vite, limitar transformações a distâncias pequenas e nunca ocultar texto.
  • [Transforms laterais causam overflow horizontal] → limitar distância por breakpoint, manter recorte no contêiner público e testar scrollWidth em ambos viewports.
  • [Muitos observers/estilos inline] → usar um único observer, custom property de índice limitada e unobserve imediato.
  • [Páginas de erro não carregam o runtime em todos os contextos] → o estado final é seguro; feature tests cobrem os cinco templates.

Migration Plan

Publicar CSS, JS e templates no mesmo bundle/commit; não há migração de dados. Rollback consiste em reverter esses assets e atributos, sem compatibilidade de schema ou limpeza operacional.

Open Questions

Nenhuma; direção, alternância mobile, execução única e limites de escopo foram aprovados no plano.