HextaUI

Chart

Recharts-Diagramme mit Theme-Farben, einem Tooltip und einer Legende, die Labels aus einer Konfiguration lesen, und Tastaturnavigation mit sichtbarem Fokusring.

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

Fügt die Komponente, die HextaUI-Theme-Tokens und alle HextaUI-Komponenten hinzu, von denen sie abhängt.

Du baust Charts mit Recharts-Komponenten und fügst die Teile aus chart nur dort hinzu, wo du sie brauchst. Recharts wird nicht umschlossen, daher gelten seine eigene Dokumentation und Upgrade-Anleitungen unverändert.

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

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

Eine ChartConfig ordnet jedem Datenschlüssel ein Label, ein optionales Icon und eine Farbe zu. Sie bleibt von den Daten getrennt, sodass eine Config mehrere Charts bedienen kann.

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>

Gib <ChartContainer /> eine Höhe, ein min-h-* oder ein aspect-*, damit sich der Chart beim ersten Rendern selbst messen kann. Ohne eines fällt er auf aspect-video zurück.

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

Jeder Config-Schlüssel wird zu einer --color-KEY-Variable, die auf seinen Chart begrenzt ist. Verweise damit auf ein Theme-Token, auf eine beliebige CSS-Farbe oder gib getrennte light- und dark-Werte an.

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

Verwende die Variable überall dort, wo Recharts eine Farbe nimmt: an Komponenten, in deinen Daten oder in Tailwind-Klassen.

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

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

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

Das Theme liefert fünf Chart-Tokens, --chart-1 bis --chart-5: Blau, Türkis, Bernstein, Violett und Rosé. In dieser Reihenfolge bleiben benachbarte Farben bei den gängigen Formen der Farbfehlsichtigkeit unterscheidbar, und jede hat mindestens 3:1 Kontrast gegenüber hellem und dunklem Hintergrund. Verwende sie der Reihe nach und lass Legende oder Labels eingeschaltet, damit Farbe nie der einzige Hinweis ist.

Schlüssel, die in einem CSS-Namen ungültig sind, etwa Mobile users, werden zu --color-Mobile-users.

Balkendiagramm

Ein Raster, eine Achse, <ChartTooltip /> und <ChartLegend />. Tooltip und Legende lesen ihre Labels und Farben aus der 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>
  )
}

Liniendiagramm

indicator="line" ordnet die Tooltip-Schlüssel den Linien zu, die sie beschreiben.

"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>
  )
}

Gestapelte Balken

Balken mit derselben stackId werden gestapelt. Runde nur die äußeren Enden ab, damit der Stapel als ein Balken wirkt.

"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>
  )
}

Horizontale Balken

Setze layout="vertical" am Chart und tausche die Achsentypen. <LabelList /> gibt jeden Wert am Ende seines Balkens aus.

"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

Jedes Segment erhält seine Farbe aus fill in den Daten. nameKey am Tooltip und an der Legende sucht das Label jedes Segments in der Config.

"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

Polare Raster und Achsen übernehmen dieselben gedämpften Linien und Labels wie kartesische.

"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

Wechsle zwischen den Indikatoren dot, line und dashed und blende das Label mit hideLabel aus. defaultIndex auf <ChartTooltip /> zeigt beim ersten Rendern einen Punkt.

"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>
  )
}

Werte formatieren

valueFormatter formatiert die Zahl und behält Indikator und Namen. labelFormatter tut dasselbe für das Label. Um stattdessen eine ganze Zeile zu ersetzen, verwende 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>
  )
}

Icons

Ein icon in der Config ersetzt den Farbmarker im Tooltip und in der Legende.

"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>
  )
}

Helle und dunkle Farben

Ein theme-Objekt wählt in jedem Theme eine andere Farbe. Wechsle das Theme der Seite, um die Änderung zu sehen.

"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>
  )
}

Negative Werte

Färbe jeden Balken mit <Cell /> und markiere Null mit <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>
  )
}

Lange Labels

Lange Serienamen werden in Legende und Tooltip umgebrochen, und große Werte bleiben daneben in einer Zeile.

"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>
  )
}

Rechts nach links

Recharts spiegelt Achsen nicht von selbst. Setze reversed auf der x-Achse und verschiebe die y-Achse nach rechts. Übergib locale an den Tooltip, um die Ziffern des Lesers anzuzeigen.

"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 schaltet accessibilityLayer standardmäßig ein, sodass der Chart ein einziger Tab-Stopp ist, durch den du Punkt für Punkt gehst.

TasteAktion
TabFokussiert den Chart und zeigt einen Fokusring.
←→Bewegt den Tooltip zum nächsten oder vorherigen Punkt. Bei einer umgekehrten Achse folgen die Tasten dem Bildschirm.
EnterZeigt den Tooltip am aktuellen Punkt an oder blendet ihn aus.
  • Charts sind für Screenreader Bilder. Benenne jeden mit einem sichtbaren Titel in der Nähe oder einem aria-label am Recharts-Chart und biete eine Tabelle an, wenn Nutzer die exakten Werte brauchen.
  • Tooltip und Legende benennen jede Serie im Text, sodass ein Leser nie allein anhand von Farben zuordnen muss.
  • Bei reduzierter Bewegung überspringt Recharts seine Einblendanimationen, und der Tooltip springt zwischen Punkten, statt zu gleiten.
  • Tooltip-Werte werden in en-US formatiert, sofern du kein locale übergibst, sodass Server und Browser denselben Text rendern.

Die Teile sitzen auf Recharts auf. Jede Recharts-Prop funktioniert weiterhin an den Chart-Komponenten, die du hineinsetzt.

Stellt die Config bereit, schreibt die Farbvariablen und rendert ein Recharts-<ResponsiveContainer /> um sein Kind. Nimmt alle <div>-Props.

PropTypStandard
configLabels, Icons und Farben für jeden Datenschlüssel.
ChartConfig–
childrenEin Recharts-Chart, etwa <BarChart />.
ReactElement–
initialDimensionDie Größe, die verwendet wird, bevor der Container gemessen wurde.
{ width: number; height: number }{ width: 320, height: 200 }
idBenennt den Chart in data-chart. Wird erzeugt, wenn nicht angegeben.
string–
AttributBeschreibung
data-slot="chart"Der Container.
data-chartDie ID, auf die die Farbvariablen begrenzt sind.
--color-KEYEine Farbvariable pro konfiguriertem Schlüssel.
PropTypStandard
label
ReactNode–
iconErsetzt den Farbmarker im Tooltip und in der Legende.
ComponentType–
colorJede CSS-Farbe oder Variable.
string–
themeVerwende es statt color für eine Farbe pro Theme.
{ light: string; dark: string }–

Das Recharts-<Tooltip />, mit kürzerem Gleiten zwischen Punkten. Nimmt alle Recharts-Tooltip-Props.

PropTypStandard
contentNormalerweise <ChartTooltipContent />.
ReactElement | (props) => ReactNode–
animationDuration
number200
animationEasing
string"ease-out"
defaultIndexZeigt den Tooltip beim ersten Rendern an diesem Punkt.
number–
PropTypStandard
indicator
"dot" | "line" | "dashed""dot"
hideLabel
booleanfalse
hideIndicator
booleanfalse
labelKeyDer Config- oder Datenschlüssel, der für das Label verwendet wird.
string–
nameKeyDer Config- oder Datenschlüssel, der für jeden Namen verwendet wird.
string–
valueFormatterFormatiert jeden Wert und behält Indikator und Namen.
(value, name, item) => ReactNode–
labelFormatter
(label, payload) => ReactNode–
formatterErsetzt jede Zeile.
(value, name, item, index, payload) => ReactNode–
localeFormatiert numerische Werte.
Intl.LocalesArgument"en-US"
colorEine Indikatorfarbe für jede Zeile.
string–
className
string–
labelClassName
string–
AttributBeschreibung
data-slot="chart-tooltip"Die Box.
data-slot="chart-tooltip-label"Das Label.
data-slot="chart-tooltip-item"Eine Zeile pro Serie.
data-slot="chart-tooltip-indicator"Der Farbschlüssel.
data-indicatorAm Schlüssel: dot, line oder dashed.
--chart-indicatorDie Farbe des Schlüssels.

Das Recharts-<Legend />. Nimmt alle Recharts-Legenden-Props und listet Serien in der Reihenfolge auf, in der du sie deklarierst, statt alphabetisch.

PropTypStandard
contentNormalerweise <ChartLegendContent />.
ReactElement | (props) => ReactNode–
itemSorternull behält die deklarierte Reihenfolge.
"value" | "dataKey" | (item) => number | string | nullnull
PropTypStandard
hideIcon
booleanfalse
nameKeyDer Config- oder Datenschlüssel, der für jeden Namen verwendet wird.
string–
className
string–
AttributBeschreibung
data-slot="chart-legend"Die Liste.
data-slot="chart-legend-item"Ein Eintrag pro Serie.
data-slot="chart-legend-indicator"Das Farbfeld.

Gibt innerhalb eines <ChartContainer /> { config } zurück, um eigene Tooltip- oder Legendeninhalte zu bauen.

In Blocks verwendet

Blocks, die auf Chart aufbauen.