Breadcrumbs

Pronto

Trilha de navegação hierárquica. Mostra onde o usuário está na árvore + permite voltar ao nível anterior.

Usar quando

Hierarquias profundas (Configurações > Equipe > Membro). Detalhe de processo (Processos > 0001234 > Documentos).

Não usar quando

Páginas top-level (sem hierarquia). Wizards (use Stepper). Lista flat sem profundidade.

Variantes

Padrão
Com ícone home
Truncado (overflow para muitos níveis)
Mono (números longos como CNJ)

Microinterações

MicrointeraçãoDisparada porComportamentoTiming
Hover linkmouseenterinkMuted → ink + underline aparece150ms ease
Truncate expandclick no ...Itens ocultos aparecem entre os fixos200ms slide
Focus ringTabOutline 2px borderInk no link em focoinstant

Acessibilidade

Acessibilidade — checklist

ARIA esperado
  • <nav aria-label="Breadcrumb">
  • <ol> com <li> em cada nível
  • Último item: aria-current="page"
  • Separadores: aria-hidden="true" (decorativos)
Notas
  • Use <nav aria-label="Breadcrumb"> para landmark de acessibilidade.
  • Último item NÃO é link (você está nele) e tem aria-current="page".
  • Truncamento (...) deve ser clicável para expandir.
  • Em mobile: mostre só os 2 últimos níveis se overflow.

Código

'use client';
import Link from 'next/link';
import { ChevronRight } from 'lucide-react';
import { T, TYPE } from '@/lib/tokens';

interface Crumb { label: string; href?: string; icon?: React.ComponentType }

export function Breadcrumbs({ items }: { items: Crumb[] }) {
  return (
    <nav aria-label="Breadcrumb">
      <ol style={{ display: 'flex', alignItems: 'center', gap: 6, listStyle: 'none', padding: 0, margin: 0 }}>
        {items.map((it, i) => {
          const isLast = i === items.length - 1;
          return (
            <li key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
              {i > 0 && <ChevronRight size={12} color={T.inkSubtle} aria-hidden />}
              {isLast ? (
                <span aria-current="page" style={{ fontSize: TYPE.sm, color: T.ink }}>{it.label}</span>
              ) : (
                <Link href={it.href!} style={{ fontSize: TYPE.sm, color: T.inkMuted }}>{it.label}</Link>
              )}
            </li>
          );
        })}
      </ol>
    </nav>
  );
}

Regras

Faça

  • Use <nav aria-label="Breadcrumb">.
  • <ol> + <li> para semantica.
  • Último item NÃO é link + aria-current="page".
  • Separador ChevronRight pequeno (12px), inkSubtle.
  • Em mobile: 2 últimos níveis se truncar.

Não faça

  • Não use breadcrumb em páginas sem hierarquia.
  • Não torne último item clicável (você JÁ está nele).
  • Não use mais de 5-6 níveis sem truncar.
  • Não esconda separadores em screen reader (mas eles devem ser aria-hidden).
  • Não force fontSize grande (breadcrumb é navegação secundária).

Tokens usados

TokenValorPapel
T.inkMuted#5A5A5Elinks inativos
T.ink#0A0A0Aitem atual + hover
T.inkSubtle#8A8A8Dseparador chevron
TYPE.sm12fontSize