Chart
Beautiful charts. Built using Recharts. Copy and paste into your apps.
Made by shadcnInstallation
Note: All up-to-date charts can be found here
Introducing Charts. A collection of chart components that you can copy and paste into your apps.
Charts are designed to look great out of the box. They work well with the other components and are fully customizable to fit your project using the Redpanda UI color system.
When to use
Use this decision tree to determine when to use Chart components and which type is most appropriate for your data:
Chart Type Guidelines
- Bar/Column Charts: Comparing quantities across categories, showing rankings or changes over time
- Line Charts: Showing trends over time, continuous data, multiple data series comparisons
- Area Charts: Cumulative values over time, showing volume and trends together
- Pie/Donut Charts: Parts of a whole, percentages, composition (limit to 5-6 segments max)
- Scatter Plots: Correlations between two variables, distributions, outlier identification
- Radar Charts: Comparing multiple variables across categories, performance metrics
Charts vs Other Components
- Use Charts when: You need to visualize quantitative data, show trends, or help users understand relationships between data points
- Use Tables when: Users need to see exact values, perform calculations, or work with detailed records
- Use Progress/Meters when: Showing simple completion status or single metric progress
- Use Statistics Cards when: Displaying key metrics without requiring trend analysis
Anatomy
The Chart system is built with composable components using Recharts and a configuration-driven approach:
Chart Component Architecture:
┌─────────────────────────────────────────────┐
│ ChartContainer (Context Provider) │
│ ┌─────────────────────────────────────────┐ │
│ │ ChartStyle (Dynamic CSS Generation) │ │
│ │ - Generates --color-KEY variables │ │
│ │ - Theme-aware color mapping │ │
│ │ - Scoped to chart instance │ │
│ └─────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────┐ │
│ │ ResponsiveContainer (Recharts) │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ Chart Type (Bar/Line/Area/Pie) │ │ │
│ │ │ ┌─────────────────────────────────┐ │ │ │
│ │ │ │ Data Elements │ │ │ │
│ │ │ │ - Bar, Line, Area segments │ │ │ │
│ │ │ │ - Uses var(--color-KEY) refs │ │ │ │
│ │ │ └─────────────────────────────────┘ │ │ │
│ │ │ ┌─────────────────────────────────┐ │ │ │
│ │ │ │ CartesianGrid (optional) │ │ │ │
│ │ │ │ - Background grid lines │ │ │ │
│ │ │ └─────────────────────────────────┘ │ │ │
│ │ │ ┌─────────────────────────────────┐ │ │ │
│ │ │ │ XAxis / YAxis (optional) │ │ │ │
│ │ │ │ - Labeled axes with formatting │ │ │ │
│ │ │ └─────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────┐ │
│ │ ChartTooltip (Custom Component) │ │
│ │ - Appears on hover/focus │ │
│ │ - Uses config for labels/colors │ │
│ │ - Supports icons and custom formatting │ │
│ └─────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────┐ │
│ │ ChartLegend (Custom Component) │ │
│ │ - Shows data series labels │ │
│ │ - Color indicators match chart │ │
│ │ - Positioned above/below chart │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
ChartConfig Structure:
{
dataKey: {
label: "Human Label", // For tooltips/legends
icon: IconComponent, // Optional icon
color: "var(--color-chart-1)", // Theme color reference
// OR
theme: { // Custom theming
light: "#color1",
dark: "#color2"
}
}
}Component Composition
- ChartContainer: Root wrapper providing theme context and responsive sizing
- ChartConfig: Configuration object defining labels, colors, and icons for data keys
- ChartStyle: Dynamic CSS generation for theme-aware color variables
- Recharts Integration: Direct use of Recharts components (Bar, Line, Area, etc.)
- Custom Components: ChartTooltip, ChartLegend for consistent theming
- Color System: Automatic color resolution from CSS variables or theme objects
- Accessibility: Built-in screen reader support via accessibilityLayer prop
Component
We use Recharts under the hood.
We designed the chart component with composition in mind. You build your charts using Recharts components and only bring in custom components, such as ChartTooltip, when and where you need it.
import { Bar, BarChart } from "recharts"
import { ChartContainer, ChartTooltipContent } from "@/components/ui/charts"
export function MyChart() {
return (
<ChartContainer>
<BarChart data={data}>
<Bar dataKey="value" />
<ChartTooltip content={<ChartTooltipContent />} />
</BarChart>
</ChartContainer>
)
}We do not wrap Recharts. This means you're not locked into an abstraction. When a new Recharts version is released, you can follow the official upgrade path to upgrade your charts.
The components are yours.
Chart Color System
Five series colors ship in theme.css, with a value per theme: an indigo-to-blue-grey family on a light page, a teal family on a dark one. Each is stepped rather than five separate hues, so a multi-series chart reads as one system. Assign them in order, chart-1 first, and never cycle: a sixth series is not a generated sixth colour, so fold it into "Other", facet the chart, or split the measure across two charts.
Current Chart Colors
These colors are already included in your theme.css file:
@theme {
--color-chart-1: #6172f3;
--color-chart-2: #3c5686;
--color-chart-3: #8ea8ee;
--color-chart-4: #c5d0e4;
--color-chart-5: #dee8ff;
}
[data-theme='dark'] {
/* Every rung is declared here: dark builds its family around its own accent — a teal, not the
light theme's indigo — in the same lightness order, so a series keeps its weight when the theme
flips. One hue throughout: stepping toward mint bought a fraction more separation between the
pale rungs and put two of them in the success green's neighbourhood. */
--color-chart-1: #26b5ac;
--color-chart-2: #18817a;
--color-chart-3: #2ed5ca;
--color-chart-4: #64f0e5;
--color-chart-5: #ddfbf7;
}Color Characteristics
- One family, stepped: the five step through a single family — indigo to blue-grey on light, one teal on dark — rather than each taking its own hue, so a chart sits inside the rest of the UI instead of competing with it.
- A value per theme: all five rungs are re-declared for a dark page. They hold the light theme's lightness order, so series 2 stays the heaviest and series 5 the lightest whichever theme is on.
- Color follows the entity, never its rank — a filter that drops series must not repaint the survivors.
Give a chart with more than about three series direct labels, not colour alone. As a
categorical palette this family is weak by design-hold rather than by accident. Measured as
OKLab ΔE between rungs adjacent in lightness, a categorical set wants 15 and neither ramp reaches
it at the pale end: light closes to 7.5 between chart-4 and chart-5, dark to 8.6
between chart-3 and chart-4. So five series resolve into fewer than five in either theme, and
a set that carries five identities on colour needs five distinct hues — a brand decision rather
than a token one.
The dark ramp also sits nearer the status palette than the old indigo did: chart-1 is ΔE 8.8
from success-strong. A teal accent has nowhere better to go — only hues 299–334 clear 15 against
every status tone, and that is the magenta band this theme deliberately left — so keep a status
colour and a series colour from meeting in the same view where you can.
Usage in Chart Config
Reference these colors in your chart configuration:
import { type ChartConfig } from "@/components/ui/chart"
const chartConfig = {
desktop: {
label: "Desktop",
color: "var(--color-chart-1)", // The series token, not a literal
},
mobile: {
label: "Mobile",
color: "var(--color-chart-2)",
},
tablet: {
label: "Tablet",
color: "var(--color-chart-3)",
},
} satisfies ChartConfigYour First Chart
Let's build your first chart. We'll build a bar chart, add a grid, axis, tooltip and legend.
The following data represents the number of desktop and mobile users for each month.
Note: Your data can be in any shape. You are not limited to the shape of the data below. Use the dataKey prop to map your data to the 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 },
]The chart config holds configuration for the chart. This is where you place human-readable strings, such as labels, icons and color tokens for theming.
import { type ChartConfig } from "@/components/ui/chart"
const chartConfig = {
desktop: {
label: "Desktop",
color: "var(--color-chart-1)",
},
mobile: {
label: "Mobile",
color: "var(--color-chart-2)",
},
} satisfies ChartConfigYou can now build your chart using Recharts components.
Important: Remember to set a min-h-[VALUE] on the ChartContainer component. This is required for the chart be responsive.
Add a Grid
Let's add a grid to the chart.
CartesianGrid component.import { Bar, BarChart, CartesianGrid } from "recharts"CartesianGrid component to your chart.<ChartContainer config={chartConfig} className="min-h-[200px] w-full">
<BarChart accessibilityLayer data={chartData}>
<CartesianGrid vertical={false} />
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
</BarChart>
</ChartContainer>Add an Axis
To add an x-axis to the chart, we'll use the XAxis component.
XAxis component.import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"XAxis component to your chart.<ChartContainer config={chartConfig} className="h-[200px] w-full">
<BarChart accessibilityLayer data={chartData}>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
tickMargin={10}
axisLine={false}
tickFormatter={(value) => value.slice(0, 3)}
/>
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
</BarChart>
</ChartContainer>Add Tooltip
So far we've only used components from Recharts. They look great out of the box thanks to some customization in the chart component.
To add a tooltip, we'll use the custom ChartTooltip and ChartTooltipContent components from chart.
ChartTooltip and ChartTooltipContent components.import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"<ChartContainer config={chartConfig} className="h-[200px] w-full">
<BarChart accessibilityLayer data={chartData}>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
tickMargin={10}
axisLine={false}
tickFormatter={(value) => value.slice(0, 3)}
/>
<ChartTooltip content={<ChartTooltipContent />} />
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
</BarChart>
</ChartContainer>Hover to see the tooltips. Easy, right? Two components, and we've got a beautiful tooltip.
Add Legend
We'll do the same for the legend. We'll use the ChartLegend and ChartLegendContent components from chart.
ChartLegend and ChartLegendContent components.import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"<ChartContainer config={chartConfig} className="h-[200px] w-full">
<BarChart accessibilityLayer 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>Done. You've built your first chart! What's next?
Chart Config
The chart config is where you define the labels, icons and colors for a chart.
It is intentionally decoupled from chart data.
This allows you to share config and color tokens between charts. It can also works independently for cases where your data or color tokens live remotely or in a different format.
import { Monitor } from "lucide-react"
import { type ChartConfig } from "@/components/ui/chart"
const chartConfig = {
desktop: {
label: "Desktop",
icon: Monitor,
// Reference Redpanda UI chart colors
color: "var(--color-chart-1)",
// OR use custom colors in any format
color: "#2563eb",
// OR use theme object with light and dark keys
theme: {
light: "var(--color-chart-1)",
dark: "var(--color-chart-2)",
},
},
} satisfies ChartConfigTheming
Charts has built-in support for theming using the Redpanda UI color system. You can use the predefined CSS variables (recommended) or custom color values in any color format, such as hex, hsl or oklch.
CSS Variables (Recommended)
The Redpanda UI theme includes optimized chart colors that automatically work with light and dark modes.
theme.cssNothing to add — the five series tokens ship in theme.css, each with a value per theme. See
Current Chart Colors above for the values.
chartConfigconst chartConfig = {
desktop: {
label: "Desktop",
color: "var(--color-chart-1)", // The series token, not a literal
},
mobile: {
label: "Mobile",
color: "var(--color-chart-2)",
},
} satisfies ChartConfigCustom Colors
You can also define your colors directly in the chart config using any color format.
Hex Colors
const chartConfig = {
desktop: {
label: "Desktop",
color: "#2563eb",
},
} satisfies ChartConfigOKLCH Colors
const chartConfig = {
desktop: {
label: "Desktop",
color: "oklch(0.65 0.2 280)", // Custom OKLCH color
},
} satisfies ChartConfigHSL Colors with CSS Variables
// Define in theme.css
:root {
--custom-chart-1: 220 70% 50%;
}
// Use in chart config
const chartConfig = {
desktop: {
label: "Desktop",
color: "hsl(var(--custom-chart-1))",
},
} satisfies ChartConfigUsing Colors
To use the theme colors in your chart, reference the colors using the format var(--color-KEY).
Components
<Bar dataKey="desktop" fill="var(--color-desktop)" />Chart Data
const chartData = [
{ browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
]Tailwind
<LabelList className="fill-[--color-desktop]" />Brand Consistency
For maximum brand consistency, use the predefined chart colors which follow the Redpanda UI design system:
const chartConfig = {
primary: { label: "Primary", color: "var(--color-chart-1)" },
secondary: { label: "Secondary", color: "var(--color-chart-2)" },
tertiary: { label: "Tertiary", color: "var(--color-chart-3)" },
quaternary: { label: "Quaternary", color: "var(--color-chart-4)" },
quinary: { label: "Quinary", color: "var(--color-chart-5)" },
} satisfies ChartConfigTooltip
A chart tooltip contains a label, name, indicator and value. You can use a combination of these to customize your tooltip.
You can turn on/off any of these using the hideLabel, hideIndicator props and customize the indicator style using the indicator prop.
Use labelKey and nameKey to use a custom key for the tooltip label and name.
Chart comes with the <ChartTooltip> and <ChartTooltipContent> components. You can use these two components to add custom tooltips to your chart.
import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"<ChartTooltip content={<ChartTooltipContent />} />Props
Use the following props to customize the tooltip.
| Prop | Type | Description |
|---|---|---|
labelKey | string | The config or data key to use for the label. |
nameKey | string | The config or data key to use for the name. |
indicator | dot line or dashed | The indicator style for the tooltip. |
hideLabel | boolean | Whether to hide the label. |
hideIndicator | boolean | Whether to hide the indicator. |
Colors
Colors are automatically referenced from the chart config using the Redpanda UI color system.
Custom
To use a custom key for tooltip label and names, use the labelKey and nameKey props.
const chartData = [
{ browser: "chrome", visitors: 187, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
]
const chartConfig = {
visitors: {
label: "Total Visitors",
},
chrome: {
label: "Chrome",
color: "var(--color-chart-1)",
},
safari: {
label: "Safari",
color: "var(--color-chart-2)",
},
} satisfies ChartConfig<ChartTooltip
content={<ChartTooltipContent labelKey="visitors" nameKey="browser" />}
/>This will use Total Visitors for label and Chrome and Safari for the tooltip names.
Legend
You can use the custom <ChartLegend> and <ChartLegendContent> components to add a legend to your chart.
import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"<ChartLegend content={<ChartLegendContent />} />Colors
Colors are automatically referenced from the chart config using the Redpanda UI color system.
Custom
To use a custom key for legend names, use the nameKey prop.
const chartData = [
{ browser: "chrome", visitors: 187, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
]
const chartConfig = {
chrome: {
label: "Chrome",
color: "var(--color-chart-1)",
},
safari: {
label: "Safari",
color: "var(--color-chart-2)",
},
} satisfies ChartConfig<ChartLegend content={<ChartLegendContent nameKey="browser" />} />This will use Chrome and Safari for the legend names.
Accessibility
You can turn on the accessibilityLayer prop to add an accessible layer to your chart.
This prop adds keyboard access and screen reader support to your charts.
<LineChart accessibilityLayer />Examples
Default
With Filter (dates)
Other chart types
Line Chart
Area Chart
Pie Chart
Radial Chart
Scatter Chart
Color Reference
Predefined Chart Colors
| Variable | Light Mode | Dark Mode | Usage |
|---|---|---|---|
--color-chart-1 | #6172f3 · oklch(0.607 0.192 274) | #26b5ac · oklch(0.700 0.114 188) | First series — the theme's accent |
--color-chart-2 | #3c5686 · oklch(0.455 0.085 262) | #18817a · oklch(0.546 0.089 188) | Second series — the heaviest rung |
--color-chart-3 | #8ea8ee · oklch(0.739 0.106 268) | #2ed5ca · oklch(0.791 0.129 188) | Third series |
--color-chart-4 | #c5d0e4 · oklch(0.855 0.030 263) | #64f0e5 · oklch(0.876 0.122 188) | Fourth series |
--color-chart-5 | #dee8ff · oklch(0.930 0.033 267) | #ddfbf7 · oklch(0.965 0.032 187) | Fifth series — the lightest rung |
Light steps through indigo into blue-grey; dark holds one teal and separates by lightness. Both are
defined in theme.css, and both hold the same lightness order so a series keeps its weight across
themes.
Credits
- We take our inspiration from Shadcn UI for the chart component and style.
Recent changes
- v1.2.0Pin shipped dependency floors to the version we develop against. Registry items now declare ranges like `^5.1.9` (the actual installed version) instead of collapsing to `^5.0.0`, so consumers start on the known-tested baseline while caret semantics still allow any compatible release within the same major.#133
- v1.1.0Theme docs refresh, readability pass on semantic foregrounds, and consumer-facing Base UI regression fixes.#121
- v1.0.0Post-Base-UI polish. Public API unchanged.#116
- v1.0.0Migrate every Radix-based primitive to `@base-ui/react@^1.4.0` (Base UI).#114
- v0.3.0Add theme-provider component to the registry with documentation and tests. Includes playground type improvements (export RegistryItem, remove as-const boilerplate) and docs site dark mode border color fix.#109