Skip to content
Extensões

Zigzag Flow

Timeline alternada com layout zigzag, animacoes de entrada staggered e status badges.

components/zigzag-flow.cssAbrir no Figma

Uso

Quando e como utilizar o componente Zigzag Flow.

  • Use para representar fluxos sequenciais ou cronologicos com layout visual alternado (esquerda/direita).
  • Ideal para timelines de projetos, historicos de atividades e fluxos de aprovacao.
  • Cada item pode conter um status badge para indicar o estado atual da etapa.
  • Suporta animacoes de entrada staggered via IntersectionObserver para revelacao progressiva ao scroll.
  • Nao recomendado para listas simples sem relacao temporal — prefira componentes de lista nesses casos.

Exemplos

Demonstracao interativa do Zigzag Flow com diferentes status e animacoes.

Carregando exemplo...

Anatomia

Estrutura interna do componente.

ElementoClasseDescricao
Container.zigzag-flowWrapper principal que define o layout zigzag.
Titulo.zigzag-flow__titleTitulo geral do componente.
Lista.zigzag-flow__itemsContainer dos itens da timeline.
Item.zigzag-flow__itemCada etapa da timeline, posicionada alternadamente.
Dot.zigzag-flow__dotMarcador circular no eixo central.
Card.zigzag-flow__cardArea de conteudo com titulo, corpo e meta.
Status.zigzag-flow__statusBadge indicando o estado da etapa.
Anexos.zigzag-flow__attachmentsLista de arquivos ou links anexados ao card.
Vazio.zigzag-flow__emptyExibido quando nao existem itens.

Animacoes

Animacoes de entrada com IntersectionObserver e stagger delay.

O Zigzag Flow utiliza IntersectionObserver para detectar quando cada item entra no viewport. Ao se tornar visivel, a classe .zigzag-flow__item--animated e adicionada com um delay staggered, criando um efeito de revelacao progressiva.

Cada item recebe um transition-delay incremental baseado no seu indice, garantindo que os cards aparecam sequencialmente de cima para baixo.

js
const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry, index) => {
    if (entry.isIntersecting) {
      entry.target.style.transitionDelay = `${index * 120}ms`;
      entry.target.classList.add('zigzag-flow__item--animated');
      observer.unobserve(entry.target);
    }
  });
}, { threshold: 0.15 });

document.querySelectorAll('.zigzag-flow__item').forEach((item) => {
  observer.observe(item);
});

Propriedades

Classes CSS disponiveis para o componente.

PropriedadeTipoDefaultDescrição
.zigzag-flowclasseContainer principal da timeline zigzag.
.zigzag-flow__titleclasseTitulo do componente.
.zigzag-flow__itemsclasseLista de itens da timeline.
.zigzag-flow__itemclasseItem individual da timeline.
.zigzag-flow__dotclasseMarcador circular no eixo central da timeline.
.zigzag-flow__dot--completedclasseDot com estilo de etapa concluida.
.zigzag-flow__dot--pendingclasseDot com estilo de etapa pendente.
.zigzag-flow__dot--errorclasseDot com estilo de etapa com erro.
.zigzag-flow__dot--warningclasseDot com estilo de etapa com alerta.
.zigzag-flow__cardclasseCard de conteudo associado ao item.
.zigzag-flow__card-titleclasseTitulo do card.
.zigzag-flow__card-bodyclasseCorpo de texto do card.
.zigzag-flow__card-metaclasseMetadados do card (data, autor, etc.).
.zigzag-flow__statusclasseBadge de status exibido no card.
.zigzag-flow__status--completedclasseBadge de status concluido.
.zigzag-flow__status--pendingclasseBadge de status pendente.
.zigzag-flow__status--errorclasseBadge de status com erro.
.zigzag-flow__status--warningclasseBadge de status com alerta.
.zigzag-flow__attachmentsclasseArea de anexos dentro do card.
.zigzag-flow__emptyclasseEstado vazio quando nao ha itens.
.zigzag-flow__item--animatedclasseModificador que ativa animacao de entrada no item.

Codigo

Snippets de implementacao.

HTML estatico

html
<div class="zigzag-flow">
  <h2 class="zigzag-flow__title">Timeline do Projeto</h2>
  <div class="zigzag-flow__items">
    <div class="zigzag-flow__item">
      <span class="zigzag-flow__dot zigzag-flow__dot--completed"></span>
      <div class="zigzag-flow__card">
        <h3 class="zigzag-flow__card-title">Etapa 1 — Planejamento</h3>
        <p class="zigzag-flow__card-body">Definicao do escopo e cronograma do projeto.</p>
        <span class="zigzag-flow__card-meta">12 jan 2026</span>
        <span class="zigzag-flow__status zigzag-flow__status--completed">Concluido</span>
      </div>
    </div>
    <div class="zigzag-flow__item">
      <span class="zigzag-flow__dot zigzag-flow__dot--pending"></span>
      <div class="zigzag-flow__card">
        <h3 class="zigzag-flow__card-title">Etapa 2 — Desenvolvimento</h3>
        <p class="zigzag-flow__card-body">Implementacao das funcionalidades principais.</p>
        <span class="zigzag-flow__card-meta">28 fev 2026</span>
        <span class="zigzag-flow__status zigzag-flow__status--pending">Pendente</span>
        <div class="zigzag-flow__attachments">
          <a href="#">spec-v2.pdf</a>
        </div>
      </div>
    </div>
    <div class="zigzag-flow__item">
      <span class="zigzag-flow__dot zigzag-flow__dot--error"></span>
      <div class="zigzag-flow__card">
        <h3 class="zigzag-flow__card-title">Etapa 3 — Revisao</h3>
        <p class="zigzag-flow__card-body">Revisao de codigo e testes de integracao.</p>
        <span class="zigzag-flow__card-meta">14 mar 2026</span>
        <span class="zigzag-flow__status zigzag-flow__status--error">Erro</span>
      </div>
    </div>
  </div>
</div>

DataLoader + Factory

html
<script>
  async function loadZigzagFlow(container, url) {
    const response = await fetch(url);
    const data = await response.json();

    const title = document.createElement('h2');
    title.className = 'zigzag-flow__title';
    title.textContent = data.title;
    container.appendChild(title);

    const items = document.createElement('div');
    items.className = 'zigzag-flow__items';

    data.steps.forEach((step) => {
      const item = document.createElement('div');
      item.className = 'zigzag-flow__item';

      item.innerHTML = `
        <span class="zigzag-flow__dot zigzag-flow__dot--${step.status}"></span>
        <div class="zigzag-flow__card">
          <h3 class="zigzag-flow__card-title">${step.title}</h3>
          <p class="zigzag-flow__card-body">${step.body}</p>
          <span class="zigzag-flow__card-meta">${step.date}</span>
          <span class="zigzag-flow__status zigzag-flow__status--${step.status}">${step.label}</span>
        </div>
      `;
      items.appendChild(item);
    });

    container.appendChild(items);
  }
</script>

<div class="zigzag-flow" id="timeline"></div>
<script>
  loadZigzagFlow(
    document.getElementById('timeline'),
    '/api/zigzag-flow.json'
  );
</script>

Auto-init via data attributes

html
<div class="zigzag-flow"
     data-component="zigzag-flow"
     data-src="/api/zigzag-flow.json"
     data-animate="true"
     data-stagger="120">
</div>

<script>
  document.querySelectorAll('[data-component="zigzag-flow"]').forEach((el) => {
    const src = el.dataset.src;
    const animate = el.dataset.animate === 'true';
    const stagger = parseInt(el.dataset.stagger, 10) || 120;

    fetch(src)
      .then((r) => r.json())
      .then((data) => {
        renderZigzagFlow(el, data);
        if (animate) initStaggerAnimation(el, stagger);
      });
  });
</script>

Estado vazio

html
<div class="zigzag-flow">
  <h2 class="zigzag-flow__title">Timeline do Projeto</h2>
  <div class="zigzag-flow__empty">
    <p>Nenhuma etapa cadastrada para este projeto.</p>
  </div>
</div>

Fonte de Dados

Formatos de dados suportados pelo componente.

O Zigzag Flow aceita dados nos formatos JSON e CSV.

JSON — estrutura esperada:

json
{
  "title": "Timeline do Projeto",
  "steps": [
    {
      "title": "Planejamento",
      "body": "Definicao do escopo e cronograma.",
      "date": "12 jan 2026",
      "status": "completed",
      "label": "Concluido"
    },
    {
      "title": "Desenvolvimento",
      "body": "Implementacao das funcionalidades.",
      "date": "28 fev 2026",
      "status": "pending",
      "label": "Pendente"
    }
  ]
}

CSV — estrutura esperada:

csv
title,body,date,status,label
Planejamento,Definicao do escopo e cronograma.,12 jan 2026,completed,Concluido
Desenvolvimento,Implementacao das funcionalidades.,28 fev 2026,pending,Pendente

Os valores validos para status sao: completed, pending, error e warning.

Dark Mode

Comportamento do componente no modo escuro.

O Zigzag Flow adapta-se automaticamente ao dark mode via CSS custom properties. Os cards recebem fundo escuro, os dots ajustam suas cores de borda e preenchimento, e os status badges mantêm contraste adequado. Nenhuma classe adicional e necessaria — basta que o tema escuro esteja ativo no :root ou no container pai.

Design System interno do GALES