Marcos N
← Voltar ao blog

React e motion design

React 19.3: View Transitions na prática

Aprenda a usar View Transitions no React 19.3 com TypeScript, respeitando acessibilidade, continuidade visual e os limites de cada tipo de animação.

Marcos N6 min de leitura
React 19.3: View Transitions na prática

Você reorganiza uma lista e os itens mudam de lugar instantaneamente. A interface está correta, mas a pessoa precisa procurar de novo o que estava olhando. View Transitions no React ajudam a comunicar essa mudança: o movimento pode preservar uma referência entre o estado anterior e o próximo.

O interesse aqui é orientar a percepção. Uma transição útil explica o que mudou sem atrasar a tarefa. Neste artigo, vou usar uma lista de projetos para mostrar essa decisão em código.

O que mudou com View Transitions no React 19.3?

O React 19.3 foi anunciado em 9 de setembro de 2026. A versão tornou estável o componente ViewTransition, anteriormente experimental. Ele integra o React à View Transition API do navegador para animar mudanças como entrada, saída e reorganização. Anúncio oficial do React 19.3.

Os exemplos abaixo pressupõem React e React DOM 19.3, com tipos compatíveis. Este portfólio, no momento da escrita, ainda usa React 19.2.6. Publicar o exemplo não significa que essa API já esteja habilitada no site.

Em projetos com framework, confira também a compatibilidade da versão instalada. Uma atualização de biblioteca merece uma validação própria; não trataria a troca do número no package.json como uma migração concluída.

A diferença entre mudar o estado e animar a mudança

O estado continua sendo a fonte de verdade. A transição é uma apresentação visual da passagem entre estados.

Segundo a referência do React, atualizações comuns e urgentes não ativam automaticamente a animação. Atualizações marcadas com startTransition, revelações de Suspense e atualizações via useDeferredValue podem ativá-la. O React coordena a chamada à API do navegador, portanto não se deve chamar document.startViewTransition() em paralelo para a mesma atualização. Referência de ViewTransition.

Essa distinção importa para UX: digitar precisa produzir resposta imediata. Eu reservaria a transição para uma mudança de composição, como ordenar resultados, e manteria o valor de um campo controlado como atualização urgente.

Exemplo em TypeScript: reorganizar projetos

O exemplo tem dados locais e duas ordens possíveis. Cada item mantém uma chave estável e sua própria fronteira de transição.

ProjectList.tsx
'use client';

import { startTransition, useState, ViewTransition } from 'react';

type Project = {
  id: string;
  title: string;
  year: number;
};

const projects: Project[] = [
  { id: 'loja', title: 'Loja', year: 2024 },
  { id: 'painel', title: 'Painel', year: 2026 },
  { id: 'agenda', title: 'Agenda', year: 2025 },
];

export function ProjectList() {
  const [newestFirst, setNewestFirst] = useState(true);
  const sorted = [...projects].sort((a, b) =>
    newestFirst ? b.year - a.year : a.year - b.year,
  );

  return (
    <section aria-labelledby="projects-title">
      <h2 id="projects-title">Projetos</h2>
      <button
        type="button"
        aria-pressed={newestFirst}
        onClick={() => {
          startTransition(() => {
            setNewestFirst(current => !current);
          });
        }}
      >
        Mais recentes primeiro
      </button>
      <ul>
        {sorted.map(project => (
          <ViewTransition key={project.id}>
            <li>
              <h3>{project.title}</h3>
              <p>{project.year}</p>
            </li>
          </ViewTransition>
        ))}
      </ul>
    </section>
  );
}

Copiar o array antes de ordenar evita modificar os dados originais. O botão mantém o foco e comunica sua seleção por aria-pressed. Não escondemos itens nem transferimos o foco para acompanhar a animação.

Minha recomendação é começar com uma lista pequena. Se houver centenas de resultados, animação e renderização precisam ser avaliadas separadamente. Uma transição agradável não corrige uma ordenação pesada nem o custo de montar centenas de cards.

Movimento reduzido precisa de tratamento explícito

O React não desabilita essas animações automaticamente quando a pessoa prefere menos movimento. A documentação recomenda tratar prefers-reduced-motion. Orientação de acessibilidade de ViewTransition.

Uma política global conservadora para a aplicação é:

view-transitions.css
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

Essa regra afeta todas as View Transitions da página. Em um design system, eu documentaria essa decisão junto da escala de duração e dos estados de foco. Assim, acessibilidade não depende de cada pessoa lembrar de acrescentar uma exceção ao componente.

View Transitions, CSS ou biblioteca de animação?

NecessidadeMinha escolha inicialLimitação a considerar
Hover de botão ou mudança de corCSSNão descreve sozinho uma troca complexa de árvore
Reorganização entre estados de interfaceView TransitionsDepende do suporte do ambiente e da integração
Arrastar com física e gestosBiblioteca especializadaAcrescenta código e uma API para manter
Narrativa sincronizada ao scrollScrollTriggerExige cuidado com layout, limpeza e responsividade
Necessidade
Hover de botão ou mudança de cor
Minha escolha inicial
CSS
Limitação a considerar
Não descreve sozinho uma troca complexa de árvore
Necessidade
Reorganização entre estados de interface
Minha escolha inicial
View Transitions
Limitação a considerar
Depende do suporte do ambiente e da integração
Necessidade
Arrastar com física e gestos
Minha escolha inicial
Biblioteca especializada
Limitação a considerar
Acrescenta código e uma API para manter
Necessidade
Narrativa sincronizada ao scroll
Minha escolha inicial
ScrollTrigger
Limitação a considerar
Exige cuidado com layout, limpeza e responsividade

O benefício de View Transitions é representar visualmente uma mudança de estado. Eu não a escolheria para uma animação contínua de fundo. Também evitaria envolver a página inteira quando apenas um resultado mudou: a fronteira escolhida determina o que a pessoa percebe como uma unidade.

Quando eu usaria isso em um projeto real?

Usaria em uma biblioteca de projetos com mudança de ordenação, numa troca entre visualizações de um mesmo conjunto ou em uma navegação que preserve um elemento reconhecível.

Meu critério seria observar a tarefa: a pessoa precisa reencontrar um item depois da atualização? Se sim, continuidade pode ajudar. Se está apenas preenchendo um formulário, eu priorizaria retorno imediato, mensagens claras e estabilidade.

Validaria a experiência sem o efeito no navegador-alvo. A funcionalidade deve continuar compreensível quando a animação não ocorrer. Depois testaria teclado, movimento reduzido, mudanças rápidas de estado e uma máquina com menos capacidade de processamento.

Erros comuns

Tratar startTransition como um acelerador

Marcar uma atualização não torna um algoritmo síncrono mais barato. Se ordenar, filtrar ou transformar dados custa muito, investigue o trabalho em si. A animação e o custo da tarefa são problemas diferentes.

Usar nomes repetidos sem precisar

Para compartilhamento entre elementos, nomes têm significado. Repetir o mesmo nome em componentes simultâneos pode causar conflito. Para uma lista comum, prefira a identificação automática do React e chaves estáveis. Restrições da API.

Avaliar só a gravação da animação

Um vídeo não mostra necessariamente foco, cliques rápidos, suporte do navegador ou legibilidade. Meu roteiro inclui interromper e repetir a interação, além de conferir se a composição final continua correta.

Conclusão

View Transitions no React fazem sentido quando ajudam a entender a relação entre estados. Comece com uma mudança pequena, preserve a semântica e teste a tarefa com o movimento desligado. Se a interface só fica compreensível durante a animação, o próximo ajuste provavelmente é de design, não de duração.