A dashboard row
import { TrendDelta } from '@arbol-ai/ui';
import { ChartLegend, ChartPanel, DonutChart, TrendChart } from '@arbol-ai/ui/charts';
const WEEK = [312, 298, 341, 356, 330, 142, 118].map((value, index) => ({
date: new Date(2026, 10, 1 + index),
value,
previous: [290, 305, 322, 318, 301, 130, 121][index] ?? null,
}));
<div className="grid gap-4 lg:grid-cols-5">
<ChartPanel
className="lg:col-span-3"
eyebrow="Last 7 days"
legend={
<ChartLegend
items={[
{ label: 'This week', color: 'chart-1' },
{ label: 'Previous week', color: 'chart-neutral' },
]}
/>
}
title="Conversations"
trend={<TrendDelta label="vs previous week" value={0.06} />}
value={1897}
>
<TrendChart
aria-label="Conversations per day"
currentLabel="This week"
data={WEEK}
previousLabel="Previous week"
/>
</ChartPanel>
<ChartPanel className="lg:col-span-2" eyebrow="Last 7 days" title="Conversations by channel">
<DonutChart
aria-label="Conversations by channel"
data={[
{ label: 'WhatsApp', value: 1102 },
{ label: 'Phone', value: 583 },
{ label: 'Web chat', value: 212 },
]}
totalLabel="conversations"
/>
</ChartPanel>
</div>Loading
The figure and the chart each hold their place until the report arrives.
import { ChartPanel, TrendChart } from '@arbol-ai/ui/charts';
<ChartPanel eyebrow="Last 30 days" isLoading title="Conversations" value={0}>
<TrendChart aria-label="Conversations per day" currentLabel="This period" data={[]} isLoading />
</ChartPanel>Nothing to draw yet
import { BarChart, ChartEmpty, ChartPanel } from '@arbol-ai/ui/charts';
<div className="grid gap-4 md:grid-cols-2">
<ChartPanel eyebrow="Today" title="Appointments by status">
<BarChart
aria-label="Appointments by status"
categories={['Attended', 'Cancelled', 'No-show']}
series={[{ label: 'Appointments', values: [0, 0, 0] }]}
/>
</ChartPanel>
<ChartPanel title="Campaign replies">
<ChartEmpty>The campaign has not sent its first message yet</ChartEmpty>
</ChartPanel>
</div>Source
The examples above are src/charts/chart-panel.examples.tsx, which the library’s tests render too.