Capítulo 67 de 108

Chart

Core Idea

Wrapper fino sobre Recharts v3 que fornece theming consistente (light/dark via CSS vars), tooltip e legend customizados — sem abstrair a API do Recharts. Você compõe o gráfico com componentes Recharts normais e só troca peças (ChartTooltip, ChartLegend) quando precisa.

Key Concepts

  • ChartConfig: objeto que mapeia cada série de dados (desktop, mobile...) para label, icon opcional e color (ou theme: { light, dark }) — desacoplado dos dados do gráfico.
  • ChartContainer: wrapper obrigatório em volta do componente Recharts; precisa de altura definida (min-h-*, h-* ou aspect-*) para o ResponsiveContainer medir corretamente.
  • var(--color-KEY): dentro do ChartContainer, cada chave do chartConfig vira uma CSS custom property acessível como var(--color-desktop), usada em fill/stroke dos componentes Recharts.
  • ChartTooltip / ChartTooltipContent: tooltip customizado; props labelKey, nameKey, indicator (dot | line | dashed), hideLabel, hideIndicator.
  • ChartLegend / ChartLegendContent: legenda customizada; prop nameKey para usar chave de dado diferente do config.
  • accessibilityLayer: prop do componente Recharts (ex. <BarChart accessibilityLayer>) que adiciona navegação por teclado e suporte a leitor de tela.
  • --chart-1 a --chart-5: tokens CSS globais de cor definidos em app/globals.css (:root e .dark), a fonte recomendada de cores para chartConfig.

Code Examples

const chartConfig = {
  desktop: { label: "Desktop", color: "var(--chart-1)" },
  mobile: { label: "Mobile", color: "var(--chart-2)" },
} satisfies ChartConfig

export function MyChart() {
  return (
    <ChartContainer config={chartConfig} className="min-h-[200px] w-full">
      <BarChart accessibilityLayer data={chartData}>
        <CartesianGrid vertical={false} />
        <XAxis dataKey="month" tickLine={false} axisLine={false} tickFormatter={(v) => v.slice(0, 3)} />
        <ChartTooltip content={<ChartTooltipContent />} />
        <ChartLegend content={<ChartLegendContent />} />
        <Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
        <Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
      </BarChart>
    </ChartContainer>
  )
}
  • O que demonstra: montagem incremental completa — grid, eixo, tooltip e legenda — todos peças opcionais do Recharts + chart.tsx.
@layer base {
  :root {
    --chart-1: oklch(0.646 0.222 41.116);
    --chart-2: oklch(0.6 0.118 184.704);
  }
  .dark {
    --chart-1: oklch(0.488 0.243 264.376);
    --chart-2: oklch(0.696 0.17 162.48);
  }
}
  • O que demonstra: definição dos tokens de cor por tema, referenciados depois como var(--chart-1) no chartConfig.
<ChartTooltip
  content={<ChartTooltipContent labelKey="visitors" nameKey="browser" />}
/>
  • O que demonstra: uso de labelKey/nameKey para mapear tooltip para chaves de dado diferentes do padrão (browser/visitors em vez do nome da série).

Reference Tables

ChartTooltipContent props

PropTypeDescription
labelKeystringConfig ou data key para o label
nameKeystringConfig ou data key para o nome
indicatordot | line | dashedEstilo do indicador visual
hideLabelbooleanOculta o label
hideIndicatorbooleanOculta o indicador

Migrando de Recharts v2 para v3

  • Use var(--chart-1) em vez de hsl(var(--chart-1)).
  • Use ChartTooltip.defaultIndex só para estado inicial; estado ativo persistente vive no seu próprio state.
  • Remova layout de <Bar> quando o <BarChart> pai já define layout.
  • Sempre mantenha altura/min-h-*/aspect-* no ChartContainer.

Anti-patterns

  • ChartContainer sem altura definida: o ResponsiveContainer interno do Recharts não consegue medir no primeiro render, gráfico não aparece.
  • Colorir com hsl(var(--chart-1)) em vez de var(--chart-1): quebrado no Recharts v3, que já espera o valor de cor completo na variável.
  • Tentar abstrair/envolver o Recharts em outra camada: o componente é deliberadamente "não wrapped" — os componentes Recharts são usados diretamente, o valor está em customizar, não abstrair.

Key Takeaways

  1. chartConfig é a camada de metadados (label/cor/ícone), desacoplada dos dados reais — pode vir de fonte remota independente do formato do dado.
  2. ChartContainer + altura mínima é obrigatório; sem isso o gráfico não renderiza.
  3. Cores referenciadas como var(--color-KEY) dentro do container, geradas a partir das chaves do chartConfig.
  4. Recharts não é abstraído: para customização avançada, use a API Recharts diretamente, não procure props extras do wrapper shadcn.
  5. accessibilityLayer é a forma recomendada (não automática) de tornar o gráfico acessível.

Connects To

  • Card (ch064): gráficos tipicamente embrulhados em Card com header/título e descrição.
  • Data Table (ch066): combinação comum em dashboards (tabela de dados + gráfico da mesma fonte).