Pular para o conteúdo
Zumkai

Micro-interações com Motion no Claude Code: layout, gestures e AnimatePresence (com case Waabi)

Micro-interações com Motion no Claude Code: layout, gestures, shared element com layoutId e AnimatePresence, prompts prontos e case Waabi.

  • motion framer micro interações claude code
  • motion layout animatepresence
Capa escura em azul-marinho com o título Micro-interações com Motion e Claude Code em tipografia condensada, régua em degradê violeta e rosa, e anéis concêntricos à direita.
Sumário
  1. O que Motion resolve em React?
  2. Como animar layout sem repintar a página?
  3. Como fazer shared element com layoutId e AnimatePresence?
  4. Motion ou View Transitions API, qual escolher?
  5. Como gerar micro-interações com Claude Code?
  6. O que o case Waabi ensina?
  7. Como manter fluidez e respeitar movimento reduzido?
  8. Perguntas frequentes sobre Motion e micro-interações
  9. Conclusão: gesto, layout e saída antes do próximo componente
  10. Fontes

Micro-interação falha quando três lógicas se misturam sem dono. O gesto precisa de resposta imediata, a lista precisa manter posição durante filtro e a saída de cena precisa explicar para onde o elemento foi. Quando tudo vira animação genérica com duração fixa, o clique parece sem resposta e a lista pisca a cada busca.

Este tutorial separa essas funções com Motion em React. Você configura motion/react, aplica gestures com springs, anima layout com transform, constrói shared element com layoutId e AnimatePresence, decide contra View Transitions API com critério técnico e gera o conjunto com Claude Code a partir de prompts com estrutura. Para o mapa geral das bibliotecas, volte ao guia completo de motion.

O que Motion resolve em React?

Código React com componente Motion em editor escuro
Foto: Negative Space via StockSnap (CC0).

Motion resolve o que pertence ao ciclo do componente. Layout que muda com filtro, item que sai de lista, botão que responde a hover e press, card que expande para detalhe. Esses casos pedem física interrompível e saída declarada, não timeline de scroll.

O contexto atual ajuda a situar a escolha. A geração v13 marca a fase após Framer Motion, com import a partir de motion/react e média de 42M de downloads por semana no npm, segundo motion.dev e npm. Os recursos centrais como layout, AnimatePresence e animateView são gratuitos, além do Motion UI lançado em jul/2026, segundo a mesma documentação. Há ainda MCP de busca com nome search-motion-codex e parceria com Cursor citada no ecossistema, com pacotes publicados no npm.

O conjunto de props cobre o tutorial inteiro. Use layout para mudança de posição e tamanho, layoutId para elemento compartilhado entre dois lugares, AnimatePresence para saída, gestures como whileHover, whileTap e whileInView para resposta e entrada, springs com stiffness e damping para física, além de useScroll para vínculo com rolagem em componentes. O bloco abaixo mostra o padrão mínimo de gesto com spring.

jsx
import { motion } from "motion/react";

export function ActionButton() {
  return (
    <motion.button
      whileHover={{ scale: 1.04 }}
      whileTap={{ scale: 0.97 }}
      transition={{ type: "spring", stiffness: 400, damping: 25 }}
    >
      Ver case
    </motion.button>
  );
}

Esse bloco curto carrega três decisões. O hover confirma foco sem roubar clique, o tap confirma press com redução pequena e o spring permite interromper no meio do gesto sem salto. Duração fixa com easing linear não entrega esse comportamento, pois não responde a troca rápida de direção.

Como animar layout sem repintar a página?

Notebook com interface em grade durante animação de layout
Foto: Negative Space via StockSnap (CC0).

Layout anima bem quando usa transform em vez de recalcular caixa. O Motion converte mudança de layout em transform, o que evita novo paint e mantém a lista estável durante filtro, busca e reordenação. Sem essa conversão, cada mudança de tamanho dispara cálculo de layout e a interface perde fluidez em lista longa.

A prop layout ativa esse comportamento no próprio elemento. Para imagens em grade, prefira layout="position", que mantém proporção e evita distorção durante resize, segundo a documentação de layout do Motion. Para contextos aninhados, use LayoutGroup para agrupar transições relacionadas, layoutScroll para painéis com scroll interno e layoutRoot para isolar a medição quando modal ou drawer vive fora do fluxo principal. Springs curtos com stiffness entre 260 e 400 e damping entre 25 e 32 mantêm resposta sem elasticidade excessiva.

jsx
import { motion } from "motion/react";

export function Grid({ items }) {
  return (
    <div className="grid">
      {items.map((item) => (
        <motion.div
          key={item.id}
          layout
          transition={{ type: "spring", stiffness: 300, damping: 30 }}
        >
          {item.title}
        </motion.div>
      ))}
    </div>
  );
}

Para imagem, a variação direta é <motion.img layout="position" />, que ancora a posição sem forçar escala do conteúdo. O erro comum aqui é animar width e height via CSS e pedir spring por cima, o que cria duas fontes de verdade para o mesmo tamanho. Deixe a medição com o Motion e use CSS só para grade e espaçamento.

a regra de layout em três checagens (o estado pertence ao componente, a mudança preserva identidade com key estável, não há troca de rota) separa layout de layoutId antes do prompt e evita shared element onde um layout simples bastaria.

Como fazer shared element com layoutId e AnimatePresence?

Tela com código de componentes durante transição shared element
Foto: Marc Chouinard via StockSnap (CC0).

Shared element é um mesmo layoutId em dois lugares. A miniatura e o detalhe declaram o mesmo identificador, e o Motion move um único elemento visual entre os dois estados em vez de desmontar um e montar outro. Sem esse vínculo, a transição vira fade genérico e o leitor perde a origem do conteúdo.

O AnimatePresence orquestra a saída. Ele mantém o elemento antigo em cena até concluir a animação de exit, o que permite cruzar saída e entrada sem buraco. O modo popLayout é útil quando a saída não deve empurrar o layout restante, pois retira o elemento do fluxo durante a animação. Para trajetórias que cruzam texto ou grade, a função arc() desenha curva legível em vez de linha reta que corta conteúdo, segundo a documentação do Motion.

jsx
import { motion, AnimatePresence } from "motion/react";

export function Card({ open, onClose }) {
  return (
    <AnimatePresence mode="popLayout">
      {open && (
        <motion.div
          layoutId="waabi-card"
          transition={{ type: "spring", stiffness: 260, damping: 28 }}
          onClick={onClose}
        />
      )}
    </AnimatePresence>
  );
}

Esse padrão pede disciplina de identidade. O layoutId deve ser único por par origem e destino, e a key da lista deve permanecer estável durante filtro. Em lista longa com dezenas de cards animados, limite o shared aos itens visíveis e use whileInView com once para o restante. Shared em excesso cria competição de medição e derruba a leitura em mobile.

Motion ou View Transitions API, qual escolher?

A escolha honesta passa por snapshot contra transform. A View Transitions API captura um snapshot do DOM e anima essa imagem estática entre estados, o que simplifica transição de documento com pouco código. O Motion anima o elemento vivo com transform, o que mantém hierarquia, eventos e possibilidade de interrupção no meio do gesto.

Essa diferença decide três casos. Interrupção favorece Motion, pois um novo gesto pode redirecionar o spring sem esperar o fim da transição. Pointer events favorecem Motion em controles que precisam continuar clicáveis durante a animação, pois snapshot congela a imagem e bloqueia interação até concluir. Custo de orquestração favorece View Transitions quando a mudança é de página inteira sem gesto concorrente, pois exige menos código de saída por componente. O recurso animateView do Motion, gratuito segundo motion.dev, atende quem quer transição de visualização sem sair do modelo de componentes.

Na prática, use View Transitions para troca de documento com snapshot suficiente e sem física concorrente. Use Motion para micro-interação de componente com hover, drag, filtro e shared element, onde interromper e manter eventos decide a sensação. Misturar os dois na mesma transição cria dupla animação sobre o mesmo pixel e deve ser evitado.

Como gerar micro-interações com Claude Code?

Geração boa separa três funções. Skill define padrão, prompt define estrutura e docs conferem API. O ponto de partida é o repositório iart-ai/web-animation-skills no GitHub, com skills que incluem micro-interaction, 60fps-animation e accessible-animation, segundo repo iart-ai. A skill de micro-interação orienta gestures, springs e saída, a de 60fps orienta transform e opacity e a acessível orienta preferência por movimento reduzido.

O prompt funciona melhor com estrutura explícita. Descreva componente, props animadas, layoutId quando houver shared, comportamento de saída e regra mobile. Um exemplo direto para card com shared é: "Build a card that expands to a detail view with layoutId and AnimatePresence using Motion." Depois complete com nomes de componentes, modo do AnimatePresence, curva com arc() quando houver cruzamento e onde LazyMotion entra para reduzir bundle.

Para bundle enxuto, use a skill jezweb Motion. Ela documenta LazyMotion com 4.6KB e useAnimate com 2.3KB para React 19 e Next 16, o que permite carregar só o subconjunto de animação usado na página. Para referência de princípios, use o material Design Motion Principles associado a Emil Kowalski, Krehel e Jhey, que organiza duração, easing e resposta a gesto com exemplos revisáveis. Para conferir API, use o MCP search-motion-codex e a parceria com Cursor citada em motion.dev e npm. O toolkit associado a wilwaldon organiza o restante do fluxo, com auditoria via Playwright MCP e Chrome DevTools MCP.

Um ponto de limite evita erro de stack. A skill gsap-react pertence ao fluxo GSAP com hook useGSAP e não entra neste tutorial, pois aqui o ciclo pertence ao Motion com layout e AnimatePresence. Para scroll com pin, scrub e parallax, aprofunde o scroll cinematográfico com GSAP e Lenis.

jsx
import { motion, useScroll } from "motion/react";

export function Reveal() {
  const { scrollYProgress } = useScroll();
  return (
    <>
      <motion.div style={{ scaleX: scrollYProgress }} className="progress" />
      <motion.section
        initial={{ opacity: 0, y: 24 }}
        whileInView={{ opacity: 1, y: 0 }}
        viewport={{ once: true, margin: "-80px" }}
      />
    </>
  );
}

Esse bloco mostra entrada por viewport sem timeline de scroll. O viewport com once evita reanimar a cada passagem, e useScroll fica reservado para progresso vinculado a barra ou indicador, não para física de gesto.

O que o case Waabi ensina?

Mesa com notebook exibindo interface com micro-interações
Foto: Negative Space via StockSnap (CC0).

Waabi funciona como prova de contenção. O site, SOTD pelo estúdio Antinomy com React, Motion e Next.js, combina canvas animation no fundo com microinteractions na interface, segundo a seleção de animação do Awwwards. O canvas cuida de textura e profundidade, enquanto o Motion cuida de resposta a gesto, entrada de seção e transição entre estados. Nenhum efeito compete com leitura de produto.

A tabela abaixo resume gesto e efeito, prop responsável e quando usar cada um. Ela funciona como triagem antes de qualquer prompt e evita pedir física onde saída simples resolve.

Gesto ou efeitoProp ou componenteQuando usar
Hover com resposta tátilwhileHover com springConfirmar foco em botões e cards sem bloquear clique
Press e solturawhileTap com springDar retorno imediato em controles pequenos e ícones
Reordenação de listalayout com springAnimar filtro, busca e grade sem remontar DOM
Imagem em gradelayout="position"Manter proporção da imagem durante resize e filtro
Entrada por scrollwhileInView e useScrollRevelar seção uma vez, com once true
Troca com elemento comumlayoutId com AnimatePresenceShared element entre thumb e detalhe com saída orquestrada
Trajetória curvaarc()Desenhar curva do shared sem cortar texto ou grade
Painel com scroll internoLayoutGroup, layoutScroll e layoutRootIsolar medição em modal, drawer ou painel com scroll próprio

O gráfico abaixo situa adoção antes de discutir stack. Motion soma média de 42M de downloads por semana no npm, contra 4,6M do GSAP no mesmo período, segundo npm, motion.dev e gsap.com. O número não diz qual é melhor. Ele diz onde cada comunidade testa mais código em produção React.

Downloads semanais no npm: Motion contra GSAP Gráfico de barras horizontais com Motion em 42 milhões e GSAP em 4,6 milhões de downloads por semana no npm. Fontes com links em Fontes. Downloads semanais no npm (em milhões) Motion 42M 42 GSAP 4,6M 4,6 Leitura: Motion concentra uso em componentes React; GSAP concentra uso em scroll com narrativa e timelines. Source: npm via motion.dev e gsap.com, 2026
Source: médias semanais no npm via motion.dev e gsap.com em 2026, com links em Fontes.

O padrão que se repete no Waabi é motivo antes de física. Uma ideia por viewport, gesto com resposta curta, saída que explica mudança e fundo em canvas sem disputa com texto. A stack React com Motion e Next.js serve a esse plano porque mantém animação próxima ao estado que a dispara.

Como manter fluidez e respeitar movimento reduzido?

Fluidez tem regra estável. Animar transform e opacity, manter springs curtos, reservar espaço para mudança de layout e auditar no navegador com Playwright MCP e Chrome DevTools MCP. Lista com layout sem key estável remapeia itens e gera salto, shared sem AnimatePresence corta saída e gesto com duração longa atrasa confirmação de clique.

Acessibilidade segue o mesmo rigor com MotionConfig. Use reducedMotion="user" para respeitar prefers-reduced-motion, com versão estática legível e sem perda de conteúdo para quem prefere menos movimento. Combine com whileInView e once para evitar reanimação a cada scroll e com useScroll apenas onde progresso precisa de vínculo real com rolagem. Em mobile, reduza shared simultâneo e prefira fade com deslocamento curto em vez de curva longa sobre texto.

Rive vs Lottie com Claude Code

Perguntas frequentes sobre Motion e micro-interações

layout e layoutId são a mesma coisa?

Não. A prop layout anima mudança de posição e tamanho no próprio elemento, como filtro de grade que reordena sem remontar DOM. O layoutId conecta dois elementos distintos que representam o mesmo conteúdo, como miniatura e detalhe em shared element. Use layout para permanência com nova geometria e layoutId para continuidade entre dois lugares, com AnimatePresence para orquestrar a saída.

Quando a View Transitions API basta?

Quando a transição é de documento e o snapshot resolve sem gesto concorrente. Se não há hover, drag ou interrupção no meio, o snapshot entrega troca limpa com pouco código. Se há gesto interrompível, pointer events durante a animação ou física com spring, prefira Motion com transform sobre o elemento vivo, segundo a documentação do Motion e o modelo da API de transições do navegador.

Qual prompt envio ao Claude Code para um card com shared element?

Comece pelo exemplo direto: "Build a card that expands to a detail view with layoutId and AnimatePresence using Motion." Depois complete com estrutura: nomes dos componentes de origem e destino, valor do layoutId, modo popLayout, curva com arc() quando houver cruzamento, springs com stiffness e damping e comportamento em mobile. Confira a API com o MCP search-motion-codex antes de gerar orquestrações longas.

Como reduzo o bundle do Motion em Next.js?

Use LazyMotion para carregar só o subconjunto usado, com 4.6KB documentados, e useAnimate para animações imperativas curtas, com 2.3KB documentados, para React 19 e Next 16, segundo a skill jezweb Motion. Carregue o provedor uma vez no topo da árvore e mantenha gestures e layout nos componentes folha. Meça o bundle após a troca, pois ganho depende de quantas props restam na página.

Conclusão: gesto, layout e saída antes do próximo componente

Micro-interação boa pede três acertos em sequência. Gestures com springs para resposta imediata e interrompível, layout com transform para filtro sem novo paint e shared element com layoutId e AnimatePresence para continuidade entre telas. A decisão contra View Transitions passa por snapshot contra transform, com atenção a interrupção e pointer events. A geração com Claude Code rende mais com skill de micro-interação, prompt com estrutura e conferência via MCP search-motion-codex.

O próximo passo depende do gargalo do projeto. Para scroll com narrativa, pin e parallax, volte ao satélite de GSAP com Lenis. Para vetor interativo com estados e loops leves, avance para o comparativo entre Rive e Lottie.

Fontes

Leia também