Movimento

Design System

Movimento contido: a luz gira, o resto só muda de estado.

O sistema quase não se mexe. Hover de cor em 150ms, menus e janelas abrem na hora, nada de quique, mola ou parallax. O efeito de marca fica em poucos lugares: a luz do .botao, o brilho do campo em foco, a chave líquida e a .estrela. Tudo para com prefers-reduced-motion.

Curvas e durações

3 tokens

Três curvas no tokens.css; as durações são valores fixos no código (não há token de duração). Aperte Repetir: as bolinhas andam com a mesma duração (900ms) para comparar só a curva.

O gráfico mostra o progresso (vertical) no tempo (horizontal).
--easecubic-bezier(.4,0,.2,1) · hover de cor e fundo, véus
--ease-outcubic-bezier(.16,1,.3,1) · entradas: seta, aviso, gaveta, barra
--ease-suavecubic-bezier(.65,0,.35,1) · abrir e fechar grupo da lateral
--b-transicaocubic-bezier(.25,1,.5,1) · hover do .botao (local, não é token)
gota da chavecubic-bezier(.3,.9,.3,1) · chave líquida (local)
lineargiros contínuos: botão, estrela, brilho, rodinha
DuraçãoEscalaCurvaO que anima
150ms--easeHover de cor e fundo (chip, fantasma, translúcido, itens, linhas de tabela), seta do combo, balões de dica.
160ms--easeSeta da .sanfona gira 180°.
200ms--ease-out · --easeBorda e fundo do campo em foco; aviso flutuante entra (ds-subir); lateral recolhe (grid-template-columns).
250ms--ease-out · --easeBrilho do campo acende; véu do topo aparece; barra superior some; gaveta e véu da gaveta.
280ms--ease-suaveGrupo da lateral abre e fecha (altura) e a seta gira 90° (opacidade em 220ms --ease).
300ms--ease-out · --easePainel sobe sobre a barra oculta; trilho da chave muda de cor; barra de progresso.
400ms--ease-outSeta do .botao avança no hover.
420msgota · --ease-outChave líquida atravessa o trilho; .revela entra (plataforma).
600ms--b-transicaoBotão da marca: fundo, faixa de luz, cor e halo no hover.
looplinearRodinha .girando 0,8s · estrela 2,6s · giro do botão 3s · halo 4,5s · brilho do campo 5s · segundo giro do botão 7,5s.
0—Menus (.popover), calendário e janela abrem na hora.
Divergência

O comentário do tokens.css e o LEIA-PRIMEIRO dizem "botão da marca: 700ms --ease-suave" (e, em Princípios, "fundo 300ms + rótulo rolando 300ms"). O código faz outra coisa: 600ms cubic-bezier(.25,1,.5,1) e não existe rótulo rolando. Esta página documenta o código.

Botão da marca

O único componente com efeito de luz. Um contorno de luz (degradê cônico) gira pela borda em 3s; no hover a faixa se abre, um halo claro respira por dentro e a seta avança 3px. Clique: desce 1px.

Ao vivo

.botao

Passe o mouse ou chegue pelo teclado (Tab): o foco ganha o mesmo efeito do hover.

Hover congelado

.ds-mov-hover

O mesmo botão preso no estado de hover (classe só desta página), para ver a luz aberta, o halo e o giro rodando.

CamadaRepousoHover / focoCódigo
Contorno de luzFaixa estreita (--b-faixa: 5%) em Aço girando em 3s linearFaixa abre para 22%, desvia 95°, luz em Bruma e brilho branco; soma-se um 2º giro de 7,5s em sentido inversoconic-gradient(from calc(var(--b-angulo) - var(--b-angulo-desvio)) …) border-box · @keyframes ds-b-gira { to { --b-angulo: 360deg } } · animation-composition: add
FundoTintaArdósia (600ms)--b-fundo → --b-fundo-hover (propriedade registrada @property, por isso a cor transiciona)
Trama de pontosPontos brancos a 30%, mascarados pela luzAcompanha o giro mais rápido.botao::before
Brilho internoInvisívelAparece (55%) e roda.botao::after, @keyframes ds-b-roda
HaloInvisível (já respirando)Aparece (90%) e respira: escala 1 → 1,2 → 1 em 4,5s.botao > span::before, @keyframes ds-b-respira
SetaParadaAvança 3px em 400ms --ease-out (.baixa desce 2, .sobe sobe 2).botao > span::after
Clique—translateY(1px) scale(.98).botao:active
Para conferir

O LEIA-PRIMEIRO diz que no hover a luz "gira mais rápido". No código, o segundo giro do hover roda em sentido inverso (reverse) e é somado ao primeiro, o que pela conta deixa o giro mais lento (120°/s − 48°/s), não mais rápido. Vale olhar ao vivo antes de mudar a regra.

Campo e chave

Os dois controles de formulário com movimento próprio: o campo acende quando recebe foco e a chave atravessa o trilho como uma gota.

Brilho do campo em foco

.campo · .brilho

Clique no campo: atrás dele gira um degradê cônico só em tons claros da Bruma, desfocado (blur 7px), em 5s contínuo. O comum.js envolve o input num <span class="brilho">.

Foco congelado

.brilho.ds-mov-foco

O campo preso no foco (classe só desta página), para ver o brilho girando sem clicar.

Chave líquida

.chave

Clique: o botão atravessa o trilho esticando como gota (1,35 × 0,8 no meio do caminho) e uma gotinha vai atrás e se funde a ele, em 420ms, sem quique. O comum.js cria a camada .gota.

PeçaMovimento
Botão (16px)translateX(18px) em 420ms cubic-bezier(.3,.9,.3,1); depois do 1º toque, ds-gota-vai/ds-gota-volta esticam a 45%.
Gotinha (8px)Mesmo caminho, 420ms cubic-bezier(.2,.7,.2,1) com 70ms de atraso.
FusãoFiltro SVG na .gota: feGaussianBlur 2 + feColorMatrix alfa 18 −8.
TrilhoCor muda em 300ms --ease (cinza → --marcado).
Sem comum.jsO botão só desliza (.trilho:last-child::after, 300ms).

Casca

Três movimentos da estrutura da tela: o grupo da lateral abre e fecha, o véu aparece quando o painel rola e a barra superior se esconde para dar espaço.

Abrir e fechar grupo da lateral

.nav-paginas

A altura vai de 0fr a 1fr em 280ms --ease-suave, a opacidade em 220ms e a seta gira 90°. Clique no grupo.

Código (como se escreve)
<!-- dentro da .lateral; o comum.js transforma o rótulo em botão e embrulha as páginas em .nav-paginas -->
<nav class="nav">
  <div class="nav-rotulo"><svg class="i"><use href="#i-pessoas"/></svg>Equipe</div>
  <a href="pessoas.html" class="ativo"><span class="com-icone"><svg class="i"><use href="#i-usuario"/></svg>Pessoas</span></a>
  <a href="agenda.html"><span class="com-icone"><svg class="i"><use href="#i-calendario"/></svg>Agenda</span></a>
</nav>

Véu do topo

.topo.rolou

Role o painel de exemplo: depois de 8px o véu (vidro V4) aparece em 250ms --ease atrás do título. Nesta página, role o painel para ver o véu real.

Título da página
role aqui ↓

Barra oculta

.casca.barra-oculta

Depois de 240px de rolagem (e só se ainda sobrar mais de 240px), a barra superior some (opacidade 250ms, sobe 12px em 300ms) e o painel sobe por cima dela (300ms --ease-out), como o Dock do Mac. Volta abaixo de 96px ou com o mouse na borda de cima. Só acima de 1024px.

Painel
Reprodução das regras do layouts.css numa casca de exemplo.

Estrela, entrada e pulsos

Os movimentos pequenos que avisam algo: a estrela brilha, o conteúdo entra uma vez, a rodinha e o halo pulsam, o símbolo em LED pulsa ao clique.

Brilho da estrela

.estrela::after

A mesma luz cônica do botão gira em loop (2,6s linear) por dentro do símbolo, recortada pela máscara.

Precisa de atenção
A estrela em 96px, só para ver o brilho.

Entrada .revela

.revela.visto

Da plataforma, não do DS: o bloco entra uma vez ao aparecer no painel (opacidade + 12px, 420ms --ease-out). Não use em página nova.

Entrada

Sobe 12px.

Uma vez

Não repete ao rolar.

Sem cascata

Todos juntos.

Rodinha

.girando

Progresso sem porcentagem: anel Bruma Clara com o topo em --acento, volta em 0,8s linear.

Aviso flutuante

avisar()

Entra subindo 6px em 200ms --ease-out no canto de baixo e some em 5s.

Código (JS)
// comum.js: cria .avisos-flutuantes > .aviso-flutuante (role="status")
avisar('Alterações salvas.', 'i-check');     // ✓ verde
avisar('Não foi possível salvar.', 'i-fechar'); // ✕ vermelho

Pulsos

ds-b-respira · simbolo-led.js

O nome vem de in + pulsare: a marca pulsa. No sistema isso aparece em dois lugares: o halo do .botao respira (escala 1 → 1,2 em 4,5s, ver "Hover congelado") e o símbolo em LED da tela de acesso solta um pulso Lima do centro a cada clique. Clique no símbolo.

Clique: pulso

Regras

4

Movimento é exceção, não decoração. Antes de animar qualquer coisa, passe por estas quatro regras.

  1. Respeite prefers-reduced-motion. Com ele ligado, o DS zera todas as transições e animações; o botão para de girar, a estrela perde o brilho, o aviso entra sem subir e o .revela já nasce visível.
  2. Um componente por vez, com aprovação. Movimento novo entra num componente só, é mostrado à Isabela e só vira padrão depois do "aprovado". Nada de animação global.
  3. GSAP rejeitado. Nada de biblioteca de animação: o movimento é CSS (transição, @keyframes, @property) e, quando precisa, poucas linhas do comum.js.
  4. Secundários sem efeito. Só o .botao tem luz. .fantasma e .translucido só trocam o fundo no hover (150ms) e encolhem 0,97 no clique.

Secundários: só o fundo muda

.fantasma · .translucido

Passe o mouse: fantasma vai para Bruma Clara com borda Bruma Profunda; translúcido para branco 85%. Sem giro, sem luz, sem ícone que anda.

Movimento reduzido

@media (prefers-reduced-motion: reduce)

A regra global do base.css e as específicas de cada efeito.

Código (CSS)
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}
@media (prefers-reduced-motion: reduce) { .botao, .botao::before, .botao::after, .botao > span::before { animation: none; } }
@media (prefers-reduced-motion: reduce) { .estrela::after { animation: none; opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .aviso-flutuante { animation: none; } }
/* plataforma.css */
@media (prefers-reduced-motion: reduce) { .revela { opacity: 1; transform: none; transition: none; } }
Faça
  • Hover de cor e fundo em 150ms --ease.
  • Entradas com --ease-out, curtas (200–420ms).
  • Menus, calendário e janelas abrindo na hora.
  • Efeito de marca só onde já existe: .botao, .brilho, .chave, .estrela.
Evite
  • Quique, mola, parallax, contador que sobe, entrada em cascata.
  • Luz, giro ou ícone que anda em botão secundário.
  • GSAP ou outra biblioteca de animação.
  • Animação nova aplicada em vários componentes de uma vez, sem aprovação.