Installation
Complete project setup first. Your configuration
must select react/aria and include your Design System ID.
pnpm exec frontfriend download chart -f react --primitive ariaReview dependencies reported by the downloader and keep your source changes in version control.
Usage
import {
ChartConfig,
ChartContainer,
ChartTooltip,
ChartTooltipContent,
ChartLegendContent,
} from "@/components/ui/chart";
import { BarChart, CartesianGrid, XAxis, Legend, Bar } from "recharts";
const chartConfig = {
desktop: {
label: "Desktop",
color: "var(--bg-brand-mid)",
},
mobile: {
label: "Mobile",
color: "var(--bg-info-mid)",
},
} satisfies ChartConfig;
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 },
];
function ChartPlayground({
height = 280,
showLegend = true,
config = chartConfig,
}: {
height?: number;
showLegend?: boolean;
config?: ChartConfig;
}) {
return (
<ChartContainer
config={config}
style={{
width: 500,
maxWidth: "100%",
height: Math.max(160, Math.min(500, height)),
}}
>
<BarChart accessibilityLayer data={chartData}>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
axisLine={false}
tickFormatter={(value: string) => value.slice(0, 3)}
/>
<ChartTooltip content={<ChartTooltipContent />} />
{showLegend && <Legend content={<ChartLegendContent />} />}
<Bar
dataKey="desktop"
fill="var(--color-desktop)"
radius={4}
isAnimationActive={false}
/>
<Bar
dataKey="mobile"
fill="var(--color-mobile)"
radius={4}
isAnimationActive={false}
/>
</BarChart>
</ChartContainer>
);
}
<ChartPlayground height={280} showLegend config={chartConfig} />; Examples
Default
import { Card } from "@/components/ui/card";
import {
ChartContainer,
ChartConfig,
ChartTooltip,
ChartTooltipContent,
ChartLegendContent,
} from "@/components/ui/chart";
import { AreaChart, CartesianGrid, XAxis, Area, Legend } from "recharts";
const chartConfig = {
desktop: {
label: "Desktop",
color: "var(--bg-brand-mid)",
},
mobile: {
label: "Mobile",
color: "var(--bg-info-mid)",
},
} satisfies ChartConfig;
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 },
];
<Card className="w-[500px] max-w-full h-[500px]">
<ChartContainer config={chartConfig} className="w-full h-[304px] relative">
<AreaChart
accessibilityLayer
data={chartData}
margin={{
left: 12,
right: 12,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
axisLine={false}
tickMargin={8}
tickFormatter={(value) => value.slice(0, 3)}
/>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent indicator="dot" />}
/>
<Area
dataKey="mobile"
type="natural"
fill="var(--color-desktop)"
fillOpacity={0.4}
stroke="var(--color-desktop)"
stackId="a"
/>
<Area
dataKey="desktop"
type="natural"
fill="var(--color-mobile)"
fillOpacity={0.4}
stroke="var(--color-mobile)"
stackId="a"
/>
<Legend content={<ChartLegendContent />} />
</AreaChart>
</ChartContainer>
</Card>; Bar Chart Example
import { Card } from "@/components/ui/card";
import {
ChartContainer,
ChartConfig,
ChartTooltip,
ChartTooltipContent,
ChartLegendContent,
} from "@/components/ui/chart";
import { BarChart, CartesianGrid, XAxis, Bar, Legend } from "recharts";
const chartConfig = {
desktop: {
label: "Desktop",
color: "var(--bg-brand-mid)",
},
mobile: {
label: "Mobile",
color: "var(--bg-info-mid)",
},
} satisfies ChartConfig;
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 },
];
<Card className="w-[500px] max-w-full h-[500px]">
<ChartContainer
config={chartConfig}
className="mx-auto aspect-square h-[400px] 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
cursor={false}
content={<ChartTooltipContent indicator="dashed" />}
/>
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
<Legend content={<ChartLegendContent />} />
</BarChart>
</ChartContainer>
</Card>; Pie Chart Example
import { Card } from "@/components/ui/card";
import {
ChartContainer,
ChartConfig,
ChartTooltip,
ChartTooltipContent,
ChartLegendContent,
} from "@/components/ui/chart";
import { PieChart, Pie, Label, Legend } from "recharts";
const pieChartConfig = {
visitors: {
label: "Visitors",
},
chrome: {
label: "Chrome",
color: "var(--bg-brand-mid)",
},
safari: {
label: "Safari",
color: "var(--bg-info-mid)",
},
firefox: {
label: "Firefox",
color: "var(--bg-positive-mid)",
},
edge: {
label: "Edge",
color: "var(--bg-warning-mid)",
},
other: {
label: "Other",
color: "var(--bg-neutral-strong)",
},
} satisfies ChartConfig;
const pieChartData = [
{ browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
{ browser: "firefox", visitors: 287, fill: "var(--color-firefox)" },
{ browser: "edge", visitors: 173, fill: "var(--color-edge)" },
{ browser: "other", visitors: 190, fill: "var(--color-other)" },
];
const total = pieChartData.reduce((acc, curr) => acc + curr.visitors, 0);
<Card className="w-[500px] max-w-full h-[500px]">
<ChartContainer
config={pieChartConfig}
className="mx-auto aspect-square h-[400px] w-full relative"
>
<PieChart>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent hideLabel />}
/>
<Pie
data={pieChartData}
dataKey="visitors"
nameKey="browser"
innerRadius={60}
strokeWidth={5}
>
<Label
content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return (
<text
x={viewBox.cx}
y={viewBox.cy}
textAnchor="middle"
dominantBaseline="middle"
>
<tspan
x={viewBox.cx}
y={viewBox.cy}
className="fill-current text-neutral-strong text-3xl font-bold"
>
{total.toLocaleString()}
</tspan>
<tspan
x={viewBox.cx}
y={(viewBox.cy || 0) + 24}
className="fill-current text-neutral-mid"
>
Visitors
</tspan>
</text>
);
}
}}
/>
</Pie>
<Legend content={<ChartLegendContent />} />
</PieChart>
</ChartContainer>
</Card>; Line Chart Example
import { Card } from "@/components/ui/card";
import {
ChartContainer,
ChartConfig,
ChartTooltip,
ChartTooltipContent,
} from "@/components/ui/chart";
import { LineChart, CartesianGrid, XAxis, Line } from "recharts";
const lineChartConfig = {
desktop: {
label: "Desktop",
color: "var(--bg-brand-mid)",
},
} satisfies ChartConfig;
const lineChartData = [
{ month: "January", desktop: 186 },
{ month: "February", desktop: 305 },
{ month: "March", desktop: 237 },
{ month: "April", desktop: 73 },
{ month: "May", desktop: 209 },
{ month: "June", desktop: 214 },
];
<Card className="w-[500px] max-w-full h-[500px]">
<ChartContainer
config={lineChartConfig}
className="mx-auto aspect-square h-[400px] w-full "
>
<LineChart
accessibilityLayer
data={lineChartData}
margin={{
left: 12,
right: 12,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
axisLine={false}
tickMargin={8}
tickFormatter={(value) => value.slice(0, 3)}
/>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent hideLabel />}
/>
<Line
dataKey="desktop"
type="natural"
stroke="var(--color-desktop)"
strokeWidth={2}
dot={false}
/>
</LineChart>
</ChartContainer>
</Card>; Radar Chart Example
import { Card } from "@/components/ui/card";
import {
ChartContainer,
ChartConfig,
ChartTooltip,
ChartTooltipContent,
} from "@/components/ui/chart";
import { RadarChart, PolarAngleAxis, PolarGrid, Radar } from "recharts";
const radarChartConfig = {
desktop: {
label: "Desktop",
color: "var(--bg-brand-mid)",
},
} satisfies ChartConfig;
const radarChartData = [
{ month: "January", desktop: 186 },
{ month: "February", desktop: 305 },
{ month: "March", desktop: 237 },
{ month: "April", desktop: 273 },
{ month: "May", desktop: 209 },
{ month: "June", desktop: 214 },
];
<Card className="w-[500px] max-w-full h-[500px]">
<ChartContainer
config={radarChartConfig}
className="mx-auto aspect-square h-[400px] w-full "
>
<RadarChart data={radarChartData}>
<ChartTooltip cursor={false} content={<ChartTooltipContent />} />
<PolarAngleAxis dataKey="month" />
<PolarGrid />
<Radar dataKey="desktop" fill="var(--color-desktop)" fillOpacity={0.6} />
</RadarChart>
</ChartContainer>
</Card>; Radial Chart Example
import { Card } from "@/components/ui/card";
import {
ChartContainer,
ChartConfig,
ChartTooltip,
ChartTooltipContent,
} from "@/components/ui/chart";
import { RadialBarChart, RadialBar } from "recharts";
const radialChartConfig = {
visitors: {
label: "Visitors",
},
chrome: {
label: "Chrome",
color: "var(--bg-brand-mid)",
},
safari: {
label: "Safari",
color: "var(--bg-info-mid)",
},
firefox: {
label: "Firefox",
color: "var(--bg-positive-mid)",
},
edge: {
label: "Edge",
color: "var(--bg-warning-mid)",
},
other: {
label: "Other",
color: "var(--bg-neutral-strong)",
},
} satisfies ChartConfig;
const radialChartData = [
{ browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
{ browser: "firefox", visitors: 287, fill: "var(--color-firefox)" },
{ browser: "edge", visitors: 173, fill: "var(--color-edge)" },
{ browser: "other", visitors: 190, fill: "var(--color-other)" },
];
<Card className="w-[500px] max-w-full h-[500px]">
<ChartContainer
config={radialChartConfig}
className="mx-auto aspect-square h-[400px] w-full "
>
<RadialBarChart data={radialChartData} innerRadius={30} outerRadius={110}>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent hideLabel nameKey="browser" />}
/>
<RadialBar dataKey="visitors" background />
</RadialBarChart>
</ChartContainer>
</Card>; API reference
Frontfriend-owned props. Native HTML and inherited primitive props remain documented by React Aria.
ChartContainer
| Prop | Type | Default | Description |
|---|---|---|---|
config | ChartConfig | — | |
initialDimension | {
width: number;
height: number;
} | INITIAL_DIMENSION |
ChartLegendContent
| Prop | Type | Default | Description |
|---|---|---|---|
hideIcon | boolean | false | |
nameKey | string | — |
ChartStyle
| Prop | Type | Default | Description |
|---|---|---|---|
config | ChartConfig | — |
ChartTooltipContent
| Prop | Type | Default | Description |
|---|---|---|---|
hideIndicator | boolean | false | |
hideLabel | boolean | false | |
indicator | "line" | "dot" | "dashed" | "dot" | |
labelKey | string | — | |
nameKey | string | — |
Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.