HextaUI

Chart

Des graphiques Recharts aux couleurs du thème, avec une infobulle et une légende qui lisent leurs libellés depuis une seule config, et une navigation au clavier avec anneau de focus visible.

Visitors
Desktop and mobile visits per day
"use client"

import * as React from "react"
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"

import {
  Card,
  CardAction,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"

const chartData = Array.from({ length: 90 }, (_, index) => {
  const date = new Date(Date.UTC(2026, 3, 1 + index))
  const wave = Math.sin(index / 6) * 60 + Math.sin(index / 2.3) * 25
  return {
    date: date.toISOString().slice(0, 10),
    desktop: Math.round(260 + wave + index * 1.6),
    mobile: Math.round(180 - wave * 0.6 + index * 1.1),
  }
})

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

const ranges = [
  { value: "90", label: "90d", name: "Last 90 days" },
  { value: "30", label: "30d", name: "Last 30 days" },
  { value: "7", label: "7d", name: "Last 7 days" },
]

const dateFormat = new Intl.DateTimeFormat("en-US", {
  month: "short",
  day: "numeric",
  timeZone: "UTC",
})

function formatDate(value: unknown) {
  return dateFormat.format(new Date(`${value}T00:00:00Z`))
}

export function ChartDemo() {
  const [range, setRange] = React.useState("90")
  const data = chartData.slice(-Number(range))

  return (
    <Card className="w-full">
      <CardHeader>
        <CardTitle>Visitors</CardTitle>
        <CardDescription>Desktop and mobile visits per day</CardDescription>
        <CardAction>
          <ToggleGroup
            variant="outline"
            size="sm"
            aria-label="Time range"
            value={[range]}
            onValueChange={(value) => {
              if (value.length > 0) {
                setRange(value[0])
              }
            }}
          >
            {ranges.map((item) => (
              <ToggleGroupItem
                key={item.value}
                value={item.value}
                aria-label={item.name}
              >
                {item.label}
              </ToggleGroupItem>
            ))}
          </ToggleGroup>
        </CardAction>
      </CardHeader>
      <CardContent>
        <ChartContainer
          aria-label="Area chart of desktop and mobile visitors per day"
          config={chartConfig}
          className="h-64 w-full"
        >
          <AreaChart data={data} margin={{ left: 12, right: 12 }}>
            <defs>
              <linearGradient id="fill-desktop" x1="0" y1="0" x2="0" y2="1">
                <stop
                  offset="5%"
                  stopColor="var(--color-desktop)"
                  stopOpacity={0.3}
                />
                <stop
                  offset="95%"
                  stopColor="var(--color-desktop)"
                  stopOpacity={0.02}
                />
              </linearGradient>
              <linearGradient id="fill-mobile" x1="0" y1="0" x2="0" y2="1">
                <stop
                  offset="5%"
                  stopColor="var(--color-mobile)"
                  stopOpacity={0.3}
                />
                <stop
                  offset="95%"
                  stopColor="var(--color-mobile)"
                  stopOpacity={0.02}
                />
              </linearGradient>
            </defs>
            <CartesianGrid vertical={false} />
            <XAxis
              dataKey="date"
              tickLine={false}
              axisLine={false}
              tickMargin={8}
              minTickGap={32}
              tickFormatter={formatDate}
            />
            <ChartTooltip
              cursor={false}
              content={
                <ChartTooltipContent
                  indicator="dot"
                  labelFormatter={formatDate}
                />
              }
            />
            <Area
              dataKey="mobile"
              type="natural"
              fill="url(#fill-mobile)"
              stroke="var(--color-mobile)"
              strokeWidth={2}
              stackId="a"
            />
            <Area
              dataKey="desktop"
              type="natural"
              fill="url(#fill-desktop)"
              stroke="var(--color-desktop)"
              strokeWidth={2}
              stackId="a"
            />
            <ChartLegend content={<ChartLegendContent />} />
          </AreaChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/chart.json

Ajoute le composant, les tokens de thème HextaUI et les composants HextaUI dont il dépend.

Vous construisez les graphiques avec les composants Recharts et n’ajoutez les parties de chart que là où vous en avez besoin. Recharts n’est pas encapsulé : sa propre documentation et ses guides de mise à niveau s’appliquent tels quels.

import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

Un ChartConfig associe chaque clé de données à un libellé, une icône facultative et une couleur. Il reste séparé des données : une même config peut servir plusieurs graphiques.

const chartConfig = {
  desktop: {
    label: "Desktop",
    color: "var(--chart-1)",
  },
  mobile: {
    label: "Mobile",
    color: "var(--chart-2)",
  },
} satisfies ChartConfig
<ChartContainer
  aria-label="Bar chart of desktop and mobile visitors by month"
  config={chartConfig}
  className="min-h-52 w-full"
>
  <BarChart data={chartData}>
    <CartesianGrid vertical={false} />
    <XAxis dataKey="month" tickLine={false} axisLine={false} />
    <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>

Donnez à <ChartContainer /> une hauteur, un min-h-* ou un aspect-* pour que le graphique puisse se mesurer au premier rendu. Sans cela, il se rabat sur aspect-video.

ChartContainer
└── BarChart / LineChart / AreaChart / …
    ├── ChartTooltip
    │   └── ChartTooltipContent
    └── ChartLegend
        └── ChartLegendContent

Chaque clé de la config devient une variable --color-KEY limitée à son graphique. Pointez-la vers un token du thème, une couleur CSS quelconque, ou donnez-lui des valeurs light et dark distinctes.

const chartConfig = {
  desktop: {
    label: "Desktop",
    icon: IconDeviceDesktop,
    color: "var(--chart-1)",
  },
  mobile: {
    label: "Mobile",
    theme: {
      light: "oklch(0.5 0.17 285)",
      dark: "oklch(0.75 0.14 190)",
    },
  },
} satisfies ChartConfig

Utilisez la variable partout où Recharts attend une couleur : sur les composants, dans vos données ou dans les classes Tailwind.

<Bar dataKey="desktop" fill="var(--color-desktop)" />

const chartData = [
  { browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
]

<LabelList className="fill-(--color-desktop)" />

Le thème fournit cinq tokens de graphique, --chart-1 à --chart-5 : bleu, sarcelle, ambre, violet et rose. Dans cet ordre, les couleurs voisines restent distinctes pour les formes courantes de daltonisme, et chacune a un contraste d’au moins 3:1 avec les arrière-plans clair et sombre. Utilisez-les dans l’ordre et gardez la légende ou les libellés actifs, pour que la couleur ne soit jamais le seul indice.

Les clés invalides dans un nom CSS, comme Mobile users, deviennent --color-Mobile-users.

Graphique en barres

Une grille, un axe, <ChartTooltip /> et <ChartLegend />. Le tooltip et la légende lisent leurs libellés et leurs couleurs dans la config.

"use client"

import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", desktop: 186, mobile: 80 },
  { month: "February", desktop: 305, mobile: 200 },
  { month: "March", desktop: 237, mobile: 120 },
  { month: "April", desktop: 73, mobile: 190 },
  { month: "May", desktop: 209, mobile: 130 },
  { month: "June", desktop: 214, mobile: 140 },
]

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

export function ChartBar() {
  return (
    <ChartContainer
      aria-label="Bar chart of desktop and mobile visitors by month"
      config={chartConfig}
      className="min-h-52 w-full"
    >
      <BarChart data={chartData}>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="month"
          tickLine={false}
          tickMargin={10}
          axisLine={false}
          tickFormatter={(value) => value.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>
  )
}

Graphique en courbes

indicator="line" associe les touches du tooltip aux lignes qu’elles décrivent.

"use client"

import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts"

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { week: "W1", signups: 412, activated: 238 },
  { week: "W2", signups: 468, activated: 301 },
  { week: "W3", signups: 395, activated: 254 },
  { week: "W4", signups: 530, activated: 362 },
  { week: "W5", signups: 588, activated: 417 },
  { week: "W6", signups: 561, activated: 431 },
  { week: "W7", signups: 642, activated: 489 },
]

const chartConfig = {
  signups: {
    label: "Sign-ups",
    color: "var(--chart-1)",
  },
  activated: {
    label: "Activated",
    color: "var(--chart-4)",
  },
} satisfies ChartConfig

export function ChartLine() {
  return (
    <ChartContainer
      aria-label="Line chart of sign-ups and activated accounts"
      config={chartConfig}
      className="h-60 w-full"
    >
      <LineChart data={chartData} margin={{ left: 4, right: 12, top: 8 }}>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="week"
          tickLine={false}
          axisLine={false}
          tickMargin={8}
        />
        <YAxis tickLine={false} axisLine={false} tickMargin={8} width={36} />
        <ChartTooltip content={<ChartTooltipContent indicator="line" />} />
        <Line
          dataKey="signups"
          type="monotone"
          stroke="var(--color-signups)"
          strokeWidth={2}
          dot={false}
          activeDot={{ r: 4 }}
        />
        <Line
          dataKey="activated"
          type="monotone"
          stroke="var(--color-activated)"
          strokeWidth={2}
          dot={false}
          activeDot={{ r: 4 }}
        />
        <ChartLegend content={<ChartLegendContent />} />
      </LineChart>
    </ChartContainer>
  )
}

Barres empilées

Les barres ayant le même stackId s’empilent. Arrondissez uniquement les extrémités extérieures, pour que la pile se lise comme une seule barre.

"use client"

import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { quarter: "Q1", starter: 120, pro: 86, team: 34 },
  { quarter: "Q2", starter: 138, pro: 104, team: 51 },
  { quarter: "Q3", starter: 131, pro: 122, team: 69 },
  { quarter: "Q4", starter: 149, pro: 141, team: 88 },
]

const chartConfig = {
  starter: {
    label: "Starter",
    color: "var(--chart-1)",
  },
  pro: {
    label: "Pro",
    color: "var(--chart-2)",
  },
  team: {
    label: "Team",
    color: "var(--chart-3)",
  },
} satisfies ChartConfig

export function ChartStacked() {
  return (
    <ChartContainer
      aria-label="Stacked bar chart of Starter, Pro and Team plans"
      config={chartConfig}
      className="h-60 w-full max-w-md"
    >
      <BarChart data={chartData}>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="quarter"
          tickLine={false}
          axisLine={false}
          tickMargin={10}
        />
        <ChartTooltip content={<ChartTooltipContent />} />
        <ChartLegend content={<ChartLegendContent />} />
        <Bar
          dataKey="starter"
          stackId="plans"
          fill="var(--color-starter)"
          radius={[0, 0, 4, 4]}
        />
        <Bar dataKey="pro" stackId="plans" fill="var(--color-pro)" />
        <Bar
          dataKey="team"
          stackId="plans"
          fill="var(--color-team)"
          radius={[4, 4, 0, 0]}
        />
      </BarChart>
    </ChartContainer>
  )
}

Barres horizontales

Définissez layout="vertical" sur le graphique et échangez les types d’axe. <LabelList /> affiche chaque valeur au bout de sa barre.

"use client"

import { Bar, BarChart, LabelList, XAxis, YAxis } from "recharts"

import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { page: "Pricing", views: 4821 },
  { page: "Docs", views: 3902 },
  { page: "Changelog", views: 2214 },
  { page: "Blog", views: 1736 },
  { page: "Careers", views: 640 },
]

const chartConfig = {
  views: {
    label: "Views",
    color: "var(--chart-1)",
  },
} satisfies ChartConfig

export function ChartHorizontal() {
  return (
    <ChartContainer
      aria-label="Horizontal bar chart of page views"
      config={chartConfig}
      className="h-56 w-full max-w-md"
    >
      <BarChart data={chartData} layout="vertical" margin={{ right: 48 }}>
        <XAxis type="number" dataKey="views" hide />
        <YAxis
          type="category"
          dataKey="page"
          tickLine={false}
          axisLine={false}
          tickMargin={8}
          width={76}
        />
        <ChartTooltip
          cursor={false}
          content={<ChartTooltipContent hideLabel />}
        />
        <Bar dataKey="views" fill="var(--color-views)" radius={4} barSize={20}>
          <LabelList
            dataKey="views"
            position="right"
            offset={8}
            className="fill-foreground"
            formatter={(value) => Number(value).toLocaleString("en-US")}
          />
        </Bar>
      </BarChart>
    </ChartContainer>
  )
}

Donut

Chaque part prend sa couleur dans fill des données. nameKey sur le tooltip et la légende recherche dans la config le libellé de chaque part.

"use client"

import { Label, Pie, PieChart } from "recharts"

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
  { browser: "safari", visitors: 200, fill: "var(--color-safari)" },
  { browser: "firefox", visitors: 187, fill: "var(--color-firefox)" },
  { browser: "edge", visitors: 173, fill: "var(--color-edge)" },
  { browser: "other", visitors: 90, fill: "var(--color-other)" },
]

const chartConfig = {
  visitors: {
    label: "Visitors",
  },
  chrome: {
    label: "Chrome",
    color: "var(--chart-1)",
  },
  safari: {
    label: "Safari",
    color: "var(--chart-2)",
  },
  firefox: {
    label: "Firefox",
    color: "var(--chart-3)",
  },
  edge: {
    label: "Edge",
    color: "var(--chart-4)",
  },
  other: {
    label: "Other",
    color: "var(--chart-5)",
  },
} satisfies ChartConfig

const total = chartData.reduce((sum, item) => sum + item.visitors, 0)

export function ChartPie() {
  return (
    <ChartContainer
      aria-label="Pie chart of visitors by browser"
      config={chartConfig}
      className="aspect-square h-72"
    >
      <PieChart>
        <ChartTooltip
          cursor={false}
          content={<ChartTooltipContent nameKey="browser" hideLabel />}
        />
        <Pie
          data={chartData}
          dataKey="visitors"
          nameKey="browser"
          innerRadius={58}
          paddingAngle={2}
          cornerRadius={4}
        >
          <Label
            content={({ viewBox }) => {
              if (!viewBox || !("cx" in viewBox)) {
                return null
              }
              return (
                <text
                  x={viewBox.cx}
                  y={viewBox.cy}
                  textAnchor="middle"
                  dominantBaseline="middle"
                >
                  <tspan
                    x={viewBox.cx}
                    y={viewBox.cy}
                    className="fill-foreground text-2xl font-semibold"
                  >
                    {total.toLocaleString("en-US")}
                  </tspan>
                  <tspan
                    x={viewBox.cx}
                    y={(viewBox.cy ?? 0) + 22}
                    className="fill-muted-foreground"
                  >
                    Visitors
                  </tspan>
                </text>
              )
            }}
          />
        </Pie>
        <ChartLegend content={<ChartLegendContent nameKey="browser" />} />
      </PieChart>
    </ChartContainer>
  )
}

Radar

Les grilles et axes polaires reprennent les mêmes traits et libellés atténués que les cartésiens.

"use client"

import { PolarAngleAxis, PolarGrid, Radar, RadarChart } from "recharts"

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { skill: "Speed", current: 82, target: 90 },
  { skill: "Quality", current: 74, target: 85 },
  { skill: "Reach", current: 61, target: 70 },
  { skill: "Retention", current: 88, target: 85 },
  { skill: "Support", current: 69, target: 80 },
  { skill: "Pricing", current: 77, target: 75 },
]

const chartConfig = {
  current: {
    label: "Current",
    color: "var(--chart-1)",
  },
  target: {
    label: "Target",
    color: "var(--chart-3)",
  },
} satisfies ChartConfig

export function ChartRadar() {
  return (
    <ChartContainer
      aria-label="Radar chart of current and target scores"
      config={chartConfig}
      className="aspect-square h-80"
    >
      <RadarChart data={chartData}>
        <ChartTooltip content={<ChartTooltipContent indicator="line" />} />
        <PolarGrid />
        <PolarAngleAxis dataKey="skill" />
        <Radar
          dataKey="current"
          stroke="var(--color-current)"
          strokeWidth={2}
          fill="var(--color-current)"
          fillOpacity={0.15}
        />
        <Radar
          dataKey="target"
          stroke="var(--color-target)"
          strokeWidth={2}
          strokeDasharray="4 4"
          fill="none"
        />
        <ChartLegend content={<ChartLegendContent />} />
      </RadarChart>
    </ChartContainer>
  )
}

Tooltip

Basculez entre les indicateurs dot, line et dashed, et masquez le libellé avec hideLabel. defaultIndex sur <ChartTooltip /> affiche un point dès le premier rendu.

"use client"

import * as React from "react"
import { Bar, BarChart, XAxis } from "recharts"

import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  type ChartTooltipContentProps,
  type ChartConfig,
} from "@/components/ui/chart"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"

const chartData = [
  { day: "Mon", running: 450, swimming: 300 },
  { day: "Tue", running: 380, swimming: 420 },
  { day: "Wed", running: 520, swimming: 120 },
  { day: "Thu", running: 140, swimming: 550 },
  { day: "Fri", running: 600, swimming: 350 },
  { day: "Sat", running: 480, swimming: 400 },
]

const chartConfig = {
  running: {
    label: "Running",
    color: "var(--chart-1)",
  },
  swimming: {
    label: "Swimming",
    color: "var(--chart-2)",
  },
} satisfies ChartConfig

type Indicator = NonNullable<ChartTooltipContentProps["indicator"]>

const indicators: Indicator[] = ["dot", "line", "dashed"]

export function ChartTooltipIndicators() {
  const [indicator, setIndicator] = React.useState<Indicator>("dot")
  const [hideLabel, setHideLabel] = React.useState(false)

  return (
    <div className="flex w-full max-w-md flex-col items-center gap-4">
      <div className="flex flex-wrap justify-center gap-2">
        <ToggleGroup
          variant="outline"
          size="sm"
          aria-label="Indicator"
          value={[indicator]}
          onValueChange={(value) => {
            if (value.length > 0) {
              setIndicator(value[0] as Indicator)
            }
          }}
        >
          {indicators.map((item) => (
            <ToggleGroupItem key={item} value={item}>
              {item}
            </ToggleGroupItem>
          ))}
        </ToggleGroup>
        <ToggleGroup
          variant="outline"
          size="sm"
          aria-label="Label"
          value={hideLabel ? ["hidden"] : []}
          onValueChange={(value) => setHideLabel(value.length > 0)}
        >
          <ToggleGroupItem value="hidden">hideLabel</ToggleGroupItem>
        </ToggleGroup>
      </div>
      <ChartContainer
        aria-label="Bar chart of running and swimming time"
        config={chartConfig}
        className="h-52 w-full"
      >
        <BarChart data={chartData}>
          <XAxis
            dataKey="day"
            tickLine={false}
            axisLine={false}
            tickMargin={10}
          />
          <ChartTooltip
            defaultIndex={2}
            content={
              <ChartTooltipContent
                indicator={indicator}
                hideLabel={hideLabel}
              />
            }
          />
          <Bar
            dataKey="running"
            stackId="a"
            fill="var(--color-running)"
            radius={[0, 0, 4, 4]}
          />
          <Bar
            dataKey="swimming"
            stackId="a"
            fill="var(--color-swimming)"
            radius={[4, 4, 0, 0]}
          />
        </BarChart>
      </ChartContainer>
    </div>
  )
}

Formatage des valeurs

valueFormatter formate le nombre et conserve l’indicateur et le nom. labelFormatter fait de même pour le libellé. Pour remplacer toute une ligne, utilisez formatter.

"use client"

import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts"

import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { month: "2026-01", revenue: 18420.5 },
  { month: "2026-02", revenue: 21310 },
  { month: "2026-03", revenue: 19875.25 },
  { month: "2026-04", revenue: 24960 },
  { month: "2026-05", revenue: 28140.75 },
  { month: "2026-06", revenue: 31295 },
]

const chartConfig = {
  revenue: {
    label: "Revenue",
    color: "var(--chart-1)",
  },
} satisfies ChartConfig

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
})

const compactCurrency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
  notation: "compact",
})

const monthFormat = new Intl.DateTimeFormat("en-US", {
  month: "long",
  year: "numeric",
  timeZone: "UTC",
})

function formatMonth(value: unknown) {
  return monthFormat.format(new Date(`${value}-01T00:00:00Z`))
}

export function ChartValueFormat() {
  return (
    <ChartContainer
      aria-label="Area chart of revenue"
      config={chartConfig}
      className="h-56 w-full max-w-md"
    >
      <AreaChart data={chartData} margin={{ left: 4, right: 12, top: 8 }}>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="month"
          tickLine={false}
          axisLine={false}
          tickMargin={8}
          tickFormatter={(value) => formatMonth(value).slice(0, 3)}
        />
        <YAxis
          tickLine={false}
          axisLine={false}
          tickMargin={8}
          width={48}
          tickFormatter={(value) => compactCurrency.format(value)}
        />
        <ChartTooltip
          content={
            <ChartTooltipContent
              indicator="line"
              labelFormatter={formatMonth}
              valueFormatter={(value) => currency.format(Number(value))}
            />
          }
        />
        <Area
          dataKey="revenue"
          type="monotone"
          stroke="var(--color-revenue)"
          strokeWidth={2}
          fill="var(--color-revenue)"
          fillOpacity={0.1}
        />
      </AreaChart>
    </ChartContainer>
  )
}

Icônes

Une icon dans la config remplace la pastille de couleur dans le tooltip et la légende.

"use client"

import {
  IconDeviceDesktop,
  IconDeviceMobile,
  IconDeviceTablet,
} from "@tabler/icons-react"
import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { month: "Jan", desktop: 186, tablet: 42, mobile: 80 },
  { month: "Feb", desktop: 305, tablet: 61, mobile: 200 },
  { month: "Mar", desktop: 237, tablet: 54, mobile: 120 },
  { month: "Apr", desktop: 173, tablet: 70, mobile: 190 },
]

const chartConfig = {
  desktop: {
    label: "Desktop",
    icon: IconDeviceDesktop,
    color: "var(--chart-1)",
  },
  tablet: {
    label: "Tablet",
    icon: IconDeviceTablet,
    color: "var(--chart-3)",
  },
  mobile: {
    label: "Mobile",
    icon: IconDeviceMobile,
    color: "var(--chart-2)",
  },
} satisfies ChartConfig

export function ChartIcons() {
  return (
    <ChartContainer
      aria-label="Bar chart of desktop, tablet and mobile visitors"
      config={chartConfig}
      className="h-56 w-full max-w-md"
    >
      <BarChart data={chartData}>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="month"
          tickLine={false}
          axisLine={false}
          tickMargin={10}
        />
        <ChartTooltip content={<ChartTooltipContent />} />
        <ChartLegend content={<ChartLegendContent />} />
        <Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
        <Bar dataKey="tablet" fill="var(--color-tablet)" radius={4} />
        <Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
      </BarChart>
    </ChartContainer>
  )
}

Couleurs claires et sombres

Un objet theme choisit une couleur différente dans chaque thème. Changez le thème du site pour la voir évoluer.

"use client"

import { CartesianGrid, Line, LineChart, XAxis } from "recharts"

import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { hour: "08:00", latency: 182 },
  { hour: "10:00", latency: 164 },
  { hour: "12:00", latency: 231 },
  { hour: "14:00", latency: 205 },
  { hour: "16:00", latency: 148 },
  { hour: "18:00", latency: 171 },
]

const chartConfig = {
  latency: {
    label: "Latency (ms)",
    theme: {
      light: "oklch(0.5 0.17 285)",
      dark: "oklch(0.75 0.14 190)",
    },
  },
} satisfies ChartConfig

export function ChartTheme() {
  return (
    <ChartContainer
      aria-label="Line chart of latency in milliseconds"
      config={chartConfig}
      className="h-52 w-full max-w-md"
    >
      <LineChart data={chartData} margin={{ left: 12, right: 12, top: 8 }}>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="hour"
          padding={{ left: 16, right: 16 }}
          tickLine={false}
          axisLine={false}
          tickMargin={8}
        />
        <ChartTooltip content={<ChartTooltipContent indicator="line" />} />
        <Line
          dataKey="latency"
          type="linear"
          stroke="var(--color-latency)"
          strokeWidth={2}
          dot={{ r: 3, fill: "var(--color-latency)" }}
        />
      </LineChart>
    </ChartContainer>
  )
}

Valeurs négatives

Colorez chaque barre avec <Cell /> et marquez le zéro avec <ReferenceLine />.

"use client"

import {
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  ReferenceLine,
  XAxis,
} from "recharts"

import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { month: "Jan", change: 12.4 },
  { month: "Feb", change: -4.1 },
  { month: "Mar", change: 8.7 },
  { month: "Apr", change: -9.3 },
  { month: "May", change: 3.2 },
  { month: "Jun", change: 15.8 },
]

const chartConfig = {
  change: {
    label: "Change",
  },
  gain: {
    label: "Gain",
    color: "var(--chart-1)",
  },
  loss: {
    label: "Loss",
    color: "var(--chart-5)",
  },
} satisfies ChartConfig

export function ChartNegative() {
  return (
    <ChartContainer
      aria-label="Bar chart of gains and losses"
      config={chartConfig}
      className="h-56 w-full max-w-md"
    >
      <BarChart data={chartData}>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="month"
          tickLine={false}
          axisLine={false}
          tickMargin={10}
        />
        <ReferenceLine y={0} />
        <ChartTooltip
          cursor={false}
          content={
            <ChartTooltipContent
              hideIndicator
              valueFormatter={(value) =>
                `${Number(value) > 0 ? "+" : ""}${value}%`
              }
            />
          }
        />
        <Bar dataKey="change" radius={4}>
          {chartData.map((item) => (
            <Cell
              key={item.month}
              fill={item.change < 0 ? "var(--color-loss)" : "var(--color-gain)"}
            />
          ))}
        </Bar>
      </BarChart>
    </ChartContainer>
  )
}

Libellés longs

Les noms de séries longs passent à la ligne dans la légende et le tooltip, et les grandes valeurs restent sur une seule ligne à côté.

"use client"

import { Bar, BarChart, XAxis } from "recharts"

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  {
    region: "North America and the Caribbean",
    enterprise: 1284032,
    midMarket: 842311,
    selfServe: 402118,
    partners: 220940,
    marketplace: 98110,
  },
  {
    region: "Europe, Middle East and Africa",
    enterprise: 1032544,
    midMarket: 760201,
    selfServe: 515720,
    partners: 180332,
    marketplace: 121004,
  },
  {
    region: "Asia Pacific",
    enterprise: 690210,
    midMarket: 612090,
    selfServe: 688402,
    partners: 140220,
    marketplace: 160550,
  },
]

const chartConfig = {
  enterprise: {
    label: "Enterprise contracts (annual)",
    color: "var(--chart-1)",
  },
  midMarket: {
    label: "Mid-market subscriptions",
    color: "var(--chart-2)",
  },
  selfServe: {
    label: "Self-serve card payments",
    color: "var(--chart-3)",
  },
  partners: {
    label: "Reseller and agency partners",
    color: "var(--chart-4)",
  },
  marketplace: {
    label: "Cloud marketplace listings",
    color: "var(--chart-5)",
  },
} satisfies ChartConfig

export function ChartLongLabels() {
  return (
    <ChartContainer
      aria-label="Bar chart of revenue by sales channel"
      config={chartConfig}
      className="h-80 w-full max-w-sm"
    >
      <BarChart data={chartData}>
        <XAxis
          dataKey="region"
          tickLine={false}
          axisLine={false}
          tickMargin={10}
          tickFormatter={(value) => value.split(/[ ,]/)[0]}
        />
        <ChartTooltip content={<ChartTooltipContent />} />
        <ChartLegend content={<ChartLegendContent />} />
        <Bar dataKey="enterprise" stackId="a" fill="var(--color-enterprise)" />
        <Bar dataKey="midMarket" stackId="a" fill="var(--color-midMarket)" />
        <Bar dataKey="selfServe" stackId="a" fill="var(--color-selfServe)" />
        <Bar dataKey="partners" stackId="a" fill="var(--color-partners)" />
        <Bar
          dataKey="marketplace"
          stackId="a"
          fill="var(--color-marketplace)"
          radius={[4, 4, 0, 0]}
        />
      </BarChart>
    </ChartContainer>
  )
}

De droite à gauche

Recharts n’inverse pas les axes tout seul. Définissez reversed sur l’axe x et déplacez l’axe y à droite. Passez locale au tooltip pour afficher les chiffres du lecteur.

"use client"

import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart"

const chartData = [
  { month: "يناير", desktop: 186, mobile: 80 },
  { month: "فبراير", desktop: 305, mobile: 200 },
  { month: "مارس", desktop: 237, mobile: 120 },
  { month: "أبريل", desktop: 73, mobile: 190 },
  { month: "مايو", desktop: 209, mobile: 130 },
  { month: "يونيو", desktop: 214, mobile: 140 },
]

const chartConfig = {
  desktop: {
    label: "سطح المكتب",
    color: "var(--chart-1)",
  },
  mobile: {
    label: "الجوال",
    color: "var(--chart-2)",
  },
} satisfies ChartConfig

const numbers = new Intl.NumberFormat("ar-EG")

export function ChartRtl() {
  return (
    <div dir="rtl" className="w-full max-w-md">
      <ChartContainer
        aria-label="مخطط أعمدة لزوار سطح المكتب والجوال"
        config={chartConfig}
        className="h-60 w-full"
      >
        <BarChart data={chartData}>
          <CartesianGrid vertical={false} />
          <XAxis
            dataKey="month"
            reversed
            tickLine={false}
            axisLine={false}
            tickMargin={10}
          />
          <YAxis
            orientation="right"
            tickLine={false}
            axisLine={false}
            tickMargin={8}
            width={36}
            tickFormatter={(value) => numbers.format(value)}
          />
          <ChartTooltip content={<ChartTooltipContent locale="ar-EG" />} />
          <ChartLegend content={<ChartLegendContent />} />
          <Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
          <Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
        </BarChart>
      </ChartContainer>
    </div>
  )
}

Recharts active accessibilityLayer par défaut : le graphique est un seul arrêt de tabulation que l’on parcourt point par point.

ToucheAction
TabDonne le focus au graphique et affiche un anneau de focus.
←→Déplace le tooltip vers le point suivant ou précédent. Sur un axe inversé, les touches suivent l’écran.
EnterAffiche ou masque le tooltip au point actuel.
  • Pour les lecteurs d’écran, les graphiques sont des images. Nommez chacun avec un titre visible à proximité ou un aria-label sur le graphique Recharts, et proposez un tableau lorsque l’on a besoin des valeurs exactes.
  • Le tooltip et la légende nomment chaque série en texte : le lecteur n’a donc jamais à s’appuyer sur les seules couleurs.
  • Avec la réduction des animations, Recharts ignore ses animations d’entrée et le tooltip saute d’un point à l’autre au lieu de glisser.
  • Les valeurs du tooltip sont formatées en en-US sauf si vous passez locale, pour que le serveur et le navigateur rendent le même texte.

Les parties se placent au-dessus de Recharts. Toutes les props de Recharts continuent de fonctionner sur les composants de graphique que vous placez à l’intérieur.

Fournit la config, écrit les variables de couleur et rend un <ResponsiveContainer /> Recharts autour de son enfant. Accepte toutes les props de <div>.

PropTypePar défaut
configLibellés, icônes et couleurs de chaque clé de données.
ChartConfig–
childrenUn graphique Recharts, comme <BarChart />.
ReactElement–
initialDimensionLa taille utilisée avant la mesure du conteneur.
{ width: number; height: number }{ width: 320, height: 200 }
idNomme le graphique dans data-chart. Généré si omis.
string–
AttributDescription
data-slot="chart"Le conteneur.
data-chartL’id auquel les variables de couleur sont limitées.
--color-KEYUne variable de couleur par clé configurée.
PropTypePar défaut
label
ReactNode–
iconRemplace la pastille de couleur dans le tooltip et la légende.
ComponentType–
colorN’importe quelle couleur ou variable CSS.
string–
themeÀ utiliser à la place de color pour une couleur par thème.
{ light: string; dark: string }–

Le <Tooltip /> de Recharts, avec un glissement plus court entre les points. Accepte toutes les props de tooltip de Recharts.

PropTypePar défaut
contentEn général <ChartTooltipContent />.
ReactElement | (props) => ReactNode–
animationDuration
number200
animationEasing
string"ease-out"
defaultIndexAffiche le tooltip à ce point au premier rendu.
number–
PropTypePar défaut
indicator
"dot" | "line" | "dashed""dot"
hideLabel
booleanfalse
hideIndicator
booleanfalse
labelKeyLa clé de la config ou des données à utiliser pour le libellé.
string–
nameKeyLa clé de la config ou des données à utiliser pour chaque nom.
string–
valueFormatterFormate chaque valeur et conserve l’indicateur et le nom.
(value, name, item) => ReactNode–
labelFormatter
(label, payload) => ReactNode–
formatterRemplace chaque ligne.
(value, name, item, index, payload) => ReactNode–
localeFormate les valeurs numériques.
Intl.LocalesArgument"en-US"
colorUne seule couleur d’indicateur pour toutes les lignes.
string–
className
string–
labelClassName
string–
AttributDescription
data-slot="chart-tooltip"La boîte.
data-slot="chart-tooltip-label"Le libellé.
data-slot="chart-tooltip-item"Une ligne par série.
data-slot="chart-tooltip-indicator"La pastille de couleur.
data-indicatorSur la clé : point, ligne ou tirets.
--chart-indicatorLa couleur de la clé.

Le <Legend /> de Recharts. Accepte toutes les props de légende de Recharts, et liste les séries dans l’ordre où vous les déclarez plutôt qu’alphabétiquement.

PropTypePar défaut
contentEn général <ChartLegendContent />.
ReactElement | (props) => ReactNode–
itemSorternull conserve l’ordre déclaré.
"value" | "dataKey" | (item) => number | string | nullnull
PropTypePar défaut
hideIcon
booleanfalse
nameKeyLa clé de la config ou des données à utiliser pour chaque nom.
string–
className
string–
AttributDescription
data-slot="chart-legend"La liste.
data-slot="chart-legend-item"Une entrée par série.
data-slot="chart-legend-indicator"L’échantillon de couleur.

Retourne { config } dans un <ChartContainer />, pour construire votre propre contenu de tooltip ou de légende.

Utilisé dans les blocks

Des blocks qui s’appuient sur Chart.