import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
ChartGrid,
ChartLegend,
ChartTooltip,
ChartXAxis,
ChartYAxis,
type ChartConfig,
} from "@/components/ui/chart";
import { LineChart, LineChartSeries } from "@/components/ui/line-chart";
const data = [
{ time: "00:00", p50: 82, p95: 210 },
{ time: "02:00", p50: 78, p95: 196 },
{ time: "04:00", p50: 75, p95: 188 },
{ time: "06:00", p50: 88, p95: 232 },
{ time: "08:00", p50: 104, p95: 286 },
{ time: "10:00", p50: 118, p95: 342 },
{ time: "12:00", p50: 126, p95: 368 },
{ time: "14:00", p50: 121, p95: 351 },
{ time: "16:00", p50: 112, p95: 318 },
{ time: "18:00", p50: 99, p95: 274 },
{ time: "20:00", p50: 92, p95: 248 },
{ time: "22:00", p50: 86, p95: 224 },
];
const config = {
p50: { label: "p50" },
p95: { label: "p95" },
} satisfies ChartConfig;
export default function LineChartLatency() {
return (
<Card className="w-full">
<CardHeader>
<CardTitle>Response time</CardTitle>
<CardDescription>Last 24 hours</CardDescription>
</CardHeader>
<CardContent>
<LineChart data={data} config={config} className="aspect-[4/3] sm:aspect-[2/1]">
<ChartGrid />
<ChartXAxis dataKey="time" />
<ChartYAxis tickFormatter={(ms: number) => `${ms} ms`} />
<ChartTooltip valueFormatter={(ms) => `${ms} ms`} />
<ChartLegend />
<LineChartSeries dataKey="p50" />
<LineChartSeries dataKey="p95" />
</LineChart>
</CardContent>
</Card>
);
}- Add the registryOnce per project
pnpm dlx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json - Add line-chart
pnpm dlx shadcn@latest add @jarvis/line-chart
Usage
import { ChartTooltip, ChartXAxis, type ChartConfig } from "@/components/ui/chart";
import { LineChart, LineChartSeries } from "@/components/ui/line-chart";
const data = [
{ month: "January", visitors: 186 },
{ month: "February", visitors: 305 },
{ month: "March", visitors: 237 },
];
const config = {
visitors: { label: "Visitors" },
} satisfies ChartConfig;
export function VisitorsChart() {
return (
<LineChart data={data} config={config}>
<ChartXAxis dataKey="month" />
<ChartTooltip />
<LineChartSeries dataKey="visitors" />
</LineChart>
);
}LineChartSeries draws one series. The axes, tooltip, legend and config come from
Chart.
Composition
Examples
Dots
dots marks every point. This one also uses curve="linear".
import { ChartGrid, ChartTooltip, ChartXAxis, type ChartConfig } from "@/components/ui/chart";
import { LineChart, LineChartSeries } from "@/components/ui/line-chart";
const data = [
{ month: "January", signups: 186 },
{ month: "February", signups: 305 },
{ month: "March", signups: 237 },
{ month: "April", signups: 273 },
{ month: "May", signups: 209 },
{ month: "June", signups: 314 },
];
const config = {
signups: { label: "Signups" },
} satisfies ChartConfig;
export default function LineChartDots() {
return (
<LineChart data={data} config={config} curve="linear" className="max-w-lg">
<ChartGrid />
<ChartXAxis dataKey="month" tickFormatter={(month: string) => month.slice(0, 3)} />
<ChartTooltip />
<LineChartSeries dataKey="signups" dots />
</LineChart>
);
}Target
A dashed series works for a target, and curve="stepAfter" holds it level until it changes. The
y-axis starts at zero; domain={["auto", "auto"]} fits it to the data instead.
import {
ChartGrid,
ChartLegend,
ChartTooltip,
ChartXAxis,
ChartYAxis,
type ChartConfig,
} from "@/components/ui/chart";
import { LineChart, LineChartSeries } from "@/components/ui/line-chart";
const data = [
{ week: "Week 1", orders: 412, target: 450 },
{ week: "Week 2", orders: 468, target: 450 },
{ week: "Week 3", orders: 431, target: 500 },
{ week: "Week 4", orders: 527, target: 500 },
{ week: "Week 5", orders: 489, target: 550 },
{ week: "Week 6", orders: 583, target: 550 },
];
const config = {
orders: { label: "Orders" },
target: { label: "Target", color: "var(--chart-5)" },
} satisfies ChartConfig;
export default function LineChartTarget() {
return (
<LineChart data={data} config={config} className="max-w-lg">
<ChartGrid />
<ChartXAxis dataKey="week" />
<ChartYAxis domain={["auto", "auto"]} />
<ChartTooltip indicator="line" />
<ChartLegend />
<LineChartSeries dataKey="orders" />
<LineChartSeries dataKey="target" curve="stepAfter" dashed />
</LineChart>
);
}Steps
curve="step" suits counts that jump between values.
import { ChartGrid, ChartTooltip, ChartXAxis, type ChartConfig } from "@/components/ui/chart";
import { LineChart, LineChartSeries } from "@/components/ui/line-chart";
const data = [
{ time: "09:00", servers: 4 },
{ time: "10:00", servers: 6 },
{ time: "11:00", servers: 6 },
{ time: "12:00", servers: 9 },
{ time: "13:00", servers: 8 },
{ time: "14:00", servers: 11 },
{ time: "15:00", servers: 7 },
{ time: "16:00", servers: 5 },
];
const config = {
servers: { label: "Servers" },
} satisfies ChartConfig;
export default function LineChartStep() {
return (
<LineChart data={data} config={config} curve="step" className="max-w-lg">
<ChartGrid />
<ChartXAxis dataKey="time" />
<ChartTooltip />
<LineChartSeries dataKey="servers" />
</LineChart>
);
}Props
| Part | Extends |
|---|---|
| LineChart | Chart |
| LineChartSeries | Line |
LineChart
| Prop | Type | Default |
|---|---|---|
configEach series' label, icon and color, keyed by its data key. | ChartConfig | — |
dataThe rows to plot, one object per point along the x-axis. | Record<string, unknown>[] | — |
curveHow lines between points are drawn. A series can set its own. | CurveType | "monotone" |
children | React.ReactNode | — |
LineChartSeries
| Prop | Type | Default |
|---|---|---|
dataKeyThe key of the series' values in each row, which also names it in the config. | string | — |
curveHow lines between points are drawn. Defaults to the chart's | CurveType | — |
dashedDraws the line dashed, as for a forecast or a target. | boolean | false |
dotsMarks every point, not just the hovered one. | boolean | false |
LineChartSeries takes the props of Recharts'
Line too, such as connectNulls.