Chart
Ten typed chart forms with ordered palette roles, responsive geometry, shared inspection and an accessible data table. Compose with Card and DataTrend for metric panels.
Xem trước
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="line" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" />Cách dùng
Khi nào dùng
- Show changes, comparisons, composition, conversion, retention or service availability from numeric data.
- Keep an accessible data table beside visual patterns and point inspection.
Khi nào không dùng
- A single current value and its change. Use DataTrend.
- Completion toward a known total. Use Progress.
- Editing individual measurements. Use Table with form controls.
Biến thể
type
Required discriminant. Each type accepts only its own data shape.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow, ChartItem, ChartRange, ChartCohortRow, ChartUptimeRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
const sampleSparkSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
}
];
const sampleChartParts: ChartItem[] = [
{
"id": "direct",
"label": "Direct",
"value": 480
},
{
"id": "search",
"label": "Search",
"value": 320
},
{
"id": "community",
"label": "Community",
"value": 180
},
{
"id": "other",
"label": "Other",
"value": 90,
"role": "other"
}
];
const sampleFunnelParts: ChartItem[] = [
{
"id": "visit",
"label": "Visited",
"value": 1200
},
{
"id": "start",
"label": "Started",
"value": 760
},
{
"id": "review",
"label": "Reviewed",
"value": 440
},
{
"id": "complete",
"label": "Completed",
"value": 260
}
];
const sampleChartRanges: ChartRange[] = [
{
"id": "discovery",
"label": "Discovery",
"start": 0,
"end": 5,
"status": "success"
},
{
"id": "prototype",
"label": "Prototype",
"start": 4,
"end": 12,
"status": "warning"
},
{
"id": "build",
"label": "Build",
"start": 10,
"end": 24,
"status": "danger"
},
{
"id": "review",
"label": "Review",
"start": 24,
"end": 24,
"status": "neutral"
}
];
const sampleCohortColumns: Array<{ id: string; label: string }> = [
{
"id": "w0",
"label": "Week 0"
},
{
"id": "w1",
"label": "Week 1"
},
{
"id": "w2",
"label": "Week 2"
},
{
"id": "w3",
"label": "Week 3"
}
];
const sampleChartCohorts: ChartCohortRow[] = [
{
"id": "a",
"label": "Cohort A",
"size": 240,
"values": [
100,
72,
54,
42
]
},
{
"id": "b",
"label": "Cohort B",
"size": 280,
"values": [
100,
75,
58,
null
]
},
{
"id": "c",
"label": "Cohort C",
"size": 310,
"values": [
100,
78,
null,
null
]
},
{
"id": "d",
"label": "Cohort D",
"size": 330,
"values": [
100,
null,
null,
null
]
}
];
const sampleChartUptime: ChartUptimeRow[] = [
{
"id": "gateway",
"label": "Gateway",
"samples": [
{
"id": "day-1",
"label": "Day 1",
"status": "success",
"availability": 100
},
{
"id": "day-2",
"label": "Day 2",
"status": "success",
"availability": 100
},
{
"id": "day-3",
"label": "Day 3",
"status": "success",
"availability": 100
},
{
"id": "day-4",
"label": "Day 4",
"status": "success",
"availability": 100
},
{
"id": "day-5",
"label": "Day 5",
"status": "success",
"availability": 100
},
{
"id": "day-6",
"label": "Day 6",
"status": "success",
"availability": 100
},
{
"id": "day-7",
"label": "Day 7",
"status": "success",
"availability": 100
},
{
"id": "day-8",
"label": "Day 8",
"status": "success",
"availability": 100
},
{
"id": "day-9",
"label": "Day 9",
"status": "success",
"availability": 100
},
{
"id": "day-10",
"label": "Day 10",
"status": "success",
"availability": 100
},
{
"id": "day-11",
"label": "Day 11",
"status": "success",
"availability": 100
},
{
"id": "day-12",
"label": "Day 12",
"status": "success",
"availability": 100
},
{
"id": "day-13",
"label": "Day 13",
"status": "success",
"availability": 100
},
{
"id": "day-14",
"label": "Day 14",
"status": "success",
"availability": 100
},
{
"id": "day-15",
"label": "Day 15",
"status": "success",
"availability": 100
},
{
"id": "day-16",
"label": "Day 16",
"status": "success",
"availability": 100
},
{
"id": "day-17",
"label": "Day 17",
"status": "success",
"availability": 100
},
{
"id": "day-18",
"label": "Day 18",
"status": "success",
"availability": 100
},
{
"id": "day-19",
"label": "Day 19",
"status": "success",
"availability": 100
},
{
"id": "day-20",
"label": "Day 20",
"status": "success",
"availability": 100
},
{
"id": "day-21",
"label": "Day 21",
"status": "success",
"availability": 100
},
{
"id": "day-22",
"label": "Day 22",
"status": "success",
"availability": 100
},
{
"id": "day-23",
"label": "Day 23",
"status": "success",
"availability": 100
},
{
"id": "day-24",
"label": "Day 24",
"status": "success",
"availability": 100
},
{
"id": "day-25",
"label": "Day 25",
"status": "success",
"availability": 100
},
{
"id": "day-26",
"label": "Day 26",
"status": "success",
"availability": 100
},
{
"id": "day-27",
"label": "Day 27",
"status": "success",
"availability": 100
},
{
"id": "day-28",
"label": "Day 28",
"status": "success",
"availability": 100
},
{
"id": "day-29",
"label": "Day 29",
"status": "success",
"availability": 100
},
{
"id": "day-30",
"label": "Day 30",
"status": "success",
"availability": 100
},
{
"id": "day-31",
"label": "Day 31",
"status": "success",
"availability": 100
},
{
"id": "day-32",
"label": "Day 32",
"status": "success",
"availability": 100
},
{
"id": "day-33",
"label": "Day 33",
"status": "success",
"availability": 100
},
{
"id": "day-34",
"label": "Day 34",
"status": "success",
"availability": 100
},
{
"id": "day-35",
"label": "Day 35",
"status": "success",
"availability": 100
},
{
"id": "day-36",
"label": "Day 36",
"status": "success",
"availability": 100
},
{
"id": "day-37",
"label": "Day 37",
"status": "success",
"availability": 100
},
{
"id": "day-38",
"label": "Day 38",
"status": "success",
"availability": 100
},
{
"id": "day-39",
"label": "Day 39",
"status": "success",
"availability": 100
},
{
"id": "day-40",
"label": "Day 40",
"status": "success",
"availability": 100
},
{
"id": "day-41",
"label": "Day 41",
"status": "success",
"availability": 100
},
{
"id": "day-42",
"label": "Day 42",
"status": "success",
"availability": 100
},
{
"id": "day-43",
"label": "Day 43",
"status": "success",
"availability": 100
},
{
"id": "day-44",
"label": "Day 44",
"status": "warning",
"availability": 99.2
},
{
"id": "day-45",
"label": "Day 45",
"status": "success",
"availability": 100
},
{
"id": "day-46",
"label": "Day 46",
"status": "success",
"availability": 100
},
{
"id": "day-47",
"label": "Day 47",
"status": "success",
"availability": 100
},
{
"id": "day-48",
"label": "Day 48",
"status": "success",
"availability": 100
},
{
"id": "day-49",
"label": "Day 49",
"status": "success",
"availability": 100
},
{
"id": "day-50",
"label": "Day 50",
"status": "success",
"availability": 100
},
{
"id": "day-51",
"label": "Day 51",
"status": "success",
"availability": 100
},
{
"id": "day-52",
"label": "Day 52",
"status": "success",
"availability": 100
},
{
"id": "day-53",
"label": "Day 53",
"status": "success",
"availability": 100
},
{
"id": "day-54",
"label": "Day 54",
"status": "success",
"availability": 100
},
{
"id": "day-55",
"label": "Day 55",
"status": "success",
"availability": 100
},
{
"id": "day-56",
"label": "Day 56",
"status": "success",
"availability": 100
},
{
"id": "day-57",
"label": "Day 57",
"status": "success",
"availability": 100
},
{
"id": "day-58",
"label": "Day 58",
"status": "success",
"availability": 100
},
{
"id": "day-59",
"label": "Day 59",
"status": "success",
"availability": 100
},
{
"id": "day-60",
"label": "Day 60",
"status": "success",
"availability": 100
},
{
"id": "day-61",
"label": "Day 61",
"status": "success",
"availability": 100
},
{
"id": "day-62",
"label": "Day 62",
"status": "success",
"availability": 100
},
{
"id": "day-63",
"label": "Day 63",
"status": "success",
"availability": 100
},
{
"id": "day-64",
"label": "Day 64",
"status": "success",
"availability": 100
},
{
"id": "day-65",
"label": "Day 65",
"status": "success",
"availability": 100
},
{
"id": "day-66",
"label": "Day 66",
"status": "success",
"availability": 100
},
{
"id": "day-67",
"label": "Day 67",
"status": "success",
"availability": 100
},
{
"id": "day-68",
"label": "Day 68",
"status": "success",
"availability": 100
},
{
"id": "day-69",
"label": "Day 69",
"status": "danger",
"availability": 96.8
},
{
"id": "day-70",
"label": "Day 70",
"status": "success",
"availability": 100
},
{
"id": "day-71",
"label": "Day 71",
"status": "success",
"availability": 100
},
{
"id": "day-72",
"label": "Day 72",
"status": "success",
"availability": 100
},
{
"id": "day-73",
"label": "Day 73",
"status": "success",
"availability": 100
},
{
"id": "day-74",
"label": "Day 74",
"status": "success",
"availability": 100
},
{
"id": "day-75",
"label": "Day 75",
"status": "success",
"availability": 100
},
{
"id": "day-76",
"label": "Day 76",
"status": "success",
"availability": 100
},
{
"id": "day-77",
"label": "Day 77",
"status": "success",
"availability": 100
},
{
"id": "day-78",
"label": "Day 78",
"status": "success",
"availability": 100
},
{
"id": "day-79",
"label": "Day 79",
"status": "success",
"availability": 100
},
{
"id": "day-80",
"label": "Day 80",
"status": "success",
"availability": 100
},
{
"id": "day-81",
"label": "Day 81",
"status": "success",
"availability": 100
},
{
"id": "day-82",
"label": "Day 82",
"status": "success",
"availability": 100
},
{
"id": "day-83",
"label": "Day 83",
"status": "success",
"availability": 100
},
{
"id": "day-84",
"label": "Day 84",
"status": "success",
"availability": 100
},
{
"id": "day-85",
"label": "Day 85",
"status": "success",
"availability": 100
},
{
"id": "day-86",
"label": "Day 86",
"status": "success",
"availability": 100
},
{
"id": "day-87",
"label": "Day 87",
"status": "success",
"availability": 100
},
{
"id": "day-88",
"label": "Day 88",
"status": "success",
"availability": 100
},
{
"id": "day-89",
"label": "Day 89",
"status": "success",
"availability": 100
},
{
"id": "day-90",
"label": "Day 90",
"status": "unknown",
"availability": null
}
]
},
{
"id": "queue",
"label": "Queue",
"samples": [
{
"id": "day-1",
"label": "Day 1",
"status": "success",
"availability": 100
},
{
"id": "day-2",
"label": "Day 2",
"status": "success",
"availability": 100
},
{
"id": "day-3",
"label": "Day 3",
"status": "success",
"availability": 100
},
{
"id": "day-4",
"label": "Day 4",
"status": "success",
"availability": 100
},
{
"id": "day-5",
"label": "Day 5",
"status": "success",
"availability": 100
},
{
"id": "day-6",
"label": "Day 6",
"status": "success",
"availability": 100
},
{
"id": "day-7",
"label": "Day 7",
"status": "success",
"availability": 100
},
{
"id": "day-8",
"label": "Day 8",
"status": "success",
"availability": 100
},
{
"id": "day-9",
"label": "Day 9",
"status": "success",
"availability": 100
},
{
"id": "day-10",
"label": "Day 10",
"status": "success",
"availability": 100
},
{
"id": "day-11",
"label": "Day 11",
"status": "success",
"availability": 100
},
{
"id": "day-12",
"label": "Day 12",
"status": "success",
"availability": 100
},
{
"id": "day-13",
"label": "Day 13",
"status": "success",
"availability": 100
},
{
"id": "day-14",
"label": "Day 14",
"status": "success",
"availability": 100
},
{
"id": "day-15",
"label": "Day 15",
"status": "success",
"availability": 100
},
{
"id": "day-16",
"label": "Day 16",
"status": "success",
"availability": 100
},
{
"id": "day-17",
"label": "Day 17",
"status": "success",
"availability": 100
},
{
"id": "day-18",
"label": "Day 18",
"status": "success",
"availability": 100
},
{
"id": "day-19",
"label": "Day 19",
"status": "success",
"availability": 100
},
{
"id": "day-20",
"label": "Day 20",
"status": "success",
"availability": 100
},
{
"id": "day-21",
"label": "Day 21",
"status": "success",
"availability": 100
},
{
"id": "day-22",
"label": "Day 22",
"status": "success",
"availability": 100
},
{
"id": "day-23",
"label": "Day 23",
"status": "success",
"availability": 100
},
{
"id": "day-24",
"label": "Day 24",
"status": "success",
"availability": 100
},
{
"id": "day-25",
"label": "Day 25",
"status": "success",
"availability": 100
},
{
"id": "day-26",
"label": "Day 26",
"status": "success",
"availability": 100
},
{
"id": "day-27",
"label": "Day 27",
"status": "success",
"availability": 100
},
{
"id": "day-28",
"label": "Day 28",
"status": "success",
"availability": 100
},
{
"id": "day-29",
"label": "Day 29",
"status": "success",
"availability": 100
},
{
"id": "day-30",
"label": "Day 30",
"status": "success",
"availability": 100
},
{
"id": "day-31",
"label": "Day 31",
"status": "success",
"availability": 100
},
{
"id": "day-32",
"label": "Day 32",
"status": "success",
"availability": 100
},
{
"id": "day-33",
"label": "Day 33",
"status": "success",
"availability": 100
},
{
"id": "day-34",
"label": "Day 34",
"status": "success",
"availability": 100
},
{
"id": "day-35",
"label": "Day 35",
"status": "success",
"availability": 100
},
{
"id": "day-36",
"label": "Day 36",
"status": "success",
"availability": 100
},
{
"id": "day-37",
"label": "Day 37",
"status": "success",
"availability": 100
},
{
"id": "day-38",
"label": "Day 38",
"status": "success",
"availability": 100
},
{
"id": "day-39",
"label": "Day 39",
"status": "success",
"availability": 100
},
{
"id": "day-40",
"label": "Day 40",
"status": "success",
"availability": 100
},
{
"id": "day-41",
"label": "Day 41",
"status": "success",
"availability": 100
},
{
"id": "day-42",
"label": "Day 42",
"status": "success",
"availability": 100
},
{
"id": "day-43",
"label": "Day 43",
"status": "success",
"availability": 100
},
{
"id": "day-44",
"label": "Day 44",
"status": "success",
"availability": 100
},
{
"id": "day-45",
"label": "Day 45",
"status": "success",
"availability": 100
},
{
"id": "day-46",
"label": "Day 46",
"status": "success",
"availability": 100
},
{
"id": "day-47",
"label": "Day 47",
"status": "success",
"availability": 100
},
{
"id": "day-48",
"label": "Day 48",
"status": "success",
"availability": 100
},
{
"id": "day-49",
"label": "Day 49",
"status": "success",
"availability": 100
},
{
"id": "day-50",
"label": "Day 50",
"status": "success",
"availability": 100
},
{
"id": "day-51",
"label": "Day 51",
"status": "success",
"availability": 100
},
{
"id": "day-52",
"label": "Day 52",
"status": "success",
"availability": 100
},
{
"id": "day-53",
"label": "Day 53",
"status": "success",
"availability": 100
},
{
"id": "day-54",
"label": "Day 54",
"status": "warning",
"availability": 99.6
},
{
"id": "day-55",
"label": "Day 55",
"status": "success",
"availability": 100
},
{
"id": "day-56",
"label": "Day 56",
"status": "success",
"availability": 100
},
{
"id": "day-57",
"label": "Day 57",
"status": "success",
"availability": 100
},
{
"id": "day-58",
"label": "Day 58",
"status": "success",
"availability": 100
},
{
"id": "day-59",
"label": "Day 59",
"status": "success",
"availability": 100
},
{
"id": "day-60",
"label": "Day 60",
"status": "success",
"availability": 100
},
{
"id": "day-61",
"label": "Day 61",
"status": "success",
"availability": 100
},
{
"id": "day-62",
"label": "Day 62",
"status": "success",
"availability": 100
},
{
"id": "day-63",
"label": "Day 63",
"status": "success",
"availability": 100
},
{
"id": "day-64",
"label": "Day 64",
"status": "success",
"availability": 100
},
{
"id": "day-65",
"label": "Day 65",
"status": "success",
"availability": 100
},
{
"id": "day-66",
"label": "Day 66",
"status": "success",
"availability": 100
},
{
"id": "day-67",
"label": "Day 67",
"status": "success",
"availability": 100
},
{
"id": "day-68",
"label": "Day 68",
"status": "success",
"availability": 100
},
{
"id": "day-69",
"label": "Day 69",
"status": "success",
"availability": 100
},
{
"id": "day-70",
"label": "Day 70",
"status": "success",
"availability": 100
},
{
"id": "day-71",
"label": "Day 71",
"status": "success",
"availability": 100
},
{
"id": "day-72",
"label": "Day 72",
"status": "success",
"availability": 100
},
{
"id": "day-73",
"label": "Day 73",
"status": "success",
"availability": 100
},
{
"id": "day-74",
"label": "Day 74",
"status": "success",
"availability": 100
},
{
"id": "day-75",
"label": "Day 75",
"status": "success",
"availability": 100
},
{
"id": "day-76",
"label": "Day 76",
"status": "success",
"availability": 100
},
{
"id": "day-77",
"label": "Day 77",
"status": "success",
"availability": 100
},
{
"id": "day-78",
"label": "Day 78",
"status": "success",
"availability": 100
},
{
"id": "day-79",
"label": "Day 79",
"status": "success",
"availability": 100
},
{
"id": "day-80",
"label": "Day 80",
"status": "success",
"availability": 100
},
{
"id": "day-81",
"label": "Day 81",
"status": "success",
"availability": 100
},
{
"id": "day-82",
"label": "Day 82",
"status": "success",
"availability": 100
},
{
"id": "day-83",
"label": "Day 83",
"status": "success",
"availability": 100
},
{
"id": "day-84",
"label": "Day 84",
"status": "success",
"availability": 100
},
{
"id": "day-85",
"label": "Day 85",
"status": "success",
"availability": 100
},
{
"id": "day-86",
"label": "Day 86",
"status": "success",
"availability": 100
},
{
"id": "day-87",
"label": "Day 87",
"status": "success",
"availability": 100
},
{
"id": "day-88",
"label": "Day 88",
"status": "success",
"availability": 100
},
{
"id": "day-89",
"label": "Day 89",
"status": "success",
"availability": 100
},
{
"id": "day-90",
"label": "Day 90",
"status": "success",
"availability": 100
}
]
}
];
<Chart type="line" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" />
<Chart type="area" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" stack="none" />
<Chart type="bar" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" orientation="vertical" layout="grouped" compact={false} />
<Chart type="sparkline" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleSparkSeries} axes grid xScale="category" />
<Chart type="composition" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartParts} />
<Chart type="donut" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartParts} />
<Chart type="funnel" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleFunnelParts} />
<Chart type="timeline" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRanges} range={[0, 28]} marker={{ value: 14, label: "Checkpoint" }} />
<Chart type="cohort" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartCohorts} columns={sampleCohortColumns} />
<Chart type="uptime" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartUptime} />table
Toggle reveals the semantic data view. Hidden keeps the table accessible with visually hidden presentation. Sparkline defaults hidden.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="line" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" />
<Chart type="line" label="Weekly activity" description="Original illustrative data." table="visible" className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" />
<Chart type="line" label="Weekly activity" description="Original illustrative data." table="hidden" className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" />xScale
Cartesian axis spacing. Numeric and time modes require finite, strictly ascending x values; time uses epoch milliseconds. Without formatX, time positions show a short UTC date.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
const sampleLinearRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 2,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 3,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 4,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 5,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 6,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 7,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="line" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" />
<Chart type="line" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleLinearRows} series={sampleChartSeries} axes grid xScale="linear" />
<Chart type="line" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="time" />stack
Area only: overlaid independent series or a nonnegative summed stack. Null breaks the stack at that row.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="area" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" stack="none" />
<Chart type="area" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" stack="normal" />orientation
Bar only: vertical or horizontal bars.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="bar" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" orientation="vertical" layout="grouped" compact={false} />
<Chart type="bar" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" orientation="horizontal" layout="grouped" compact={false} />layout
Bar only: grouped, signed stacked or nonnegative percentage composition. Percentage rows with zero totals stay empty.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="bar" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" orientation="vertical" layout="grouped" compact={false} />
<Chart type="bar" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" orientation="vertical" layout="stacked" compact={false} />
<Chart type="bar" label="Weekly activity" description="Original illustrative data." className="w-full min-w-0" data={sampleChartRows} series={sampleChartSeries} axes grid xScale="category" orientation="vertical" layout="percentage" compact={false} />Ví dụ
Three-series line
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="line" label="Weekly activity" data={sampleChartRows} series={sampleChartSeries} />Overlaid areas
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="area" label="Audience over time" data={sampleChartRows} series={sampleChartSeries} stack="none" />Stacked areas
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="area" label="Allocation over time" data={sampleChartRows} series={sampleChartSeries} stack="normal" />Vertical grouped bars
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="bar" label="Grouped activity" data={sampleChartRows} series={sampleChartSeries} orientation="vertical" layout="grouped" />Vertical stacked bars
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="bar" label="Stacked activity" data={sampleChartRows} series={sampleChartSeries} orientation="vertical" layout="stacked" />Vertical percentage bars
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="bar" label="Percentage activity" data={sampleChartRows} series={sampleChartSeries} orientation="vertical" layout="percentage" />Horizontal grouped bars
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="bar" label="Grouped activity" data={sampleChartRows} series={sampleChartSeries} orientation="horizontal" layout="grouped" />Horizontal stacked bars
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="bar" label="Stacked activity" data={sampleChartRows} series={sampleChartSeries} orientation="horizontal" layout="stacked" />Horizontal percentage bars
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="bar" label="Percentage activity" data={sampleChartRows} series={sampleChartSeries} orientation="horizontal" layout="percentage" />Compact table bar
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartRow, ChartSeries } from "@/components/ui/chart"
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
const sampleSparkSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
}
];
<Chart type="bar" label="Views against a shared maximum" data={sampleChartRows} series={sampleSparkSeries} orientation="horizontal" compact domain={[0, 600]} table="hidden" />Sparkline
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartRow, ChartSeries } from "@/components/ui/chart"
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
const sampleSparkSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
}
];
<Chart type="sparkline" label="Views this week" data={sampleChartRows} series={sampleSparkSeries} />Composition
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartItem } from "@/components/ui/chart"
const sampleChartParts: ChartItem[] = [
{
"id": "direct",
"label": "Direct",
"value": 480
},
{
"id": "search",
"label": "Search",
"value": 320
},
{
"id": "community",
"label": "Community",
"value": 180
},
{
"id": "other",
"label": "Other",
"value": 90,
"role": "other"
}
];
<Chart type="composition" label="Traffic sources" data={sampleChartParts} />Donut
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartItem } from "@/components/ui/chart"
const sampleChartParts: ChartItem[] = [
{
"id": "direct",
"label": "Direct",
"value": 480
},
{
"id": "search",
"label": "Search",
"value": 320
},
{
"id": "community",
"label": "Community",
"value": 180
},
{
"id": "other",
"label": "Other",
"value": 90,
"role": "other"
}
];
<Chart type="donut" label="Traffic sources" data={sampleChartParts} />Ordered funnel
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartItem } from "@/components/ui/chart"
const sampleFunnelParts: ChartItem[] = [
{
"id": "visit",
"label": "Visited",
"value": 1200
},
{
"id": "start",
"label": "Started",
"value": 760
},
{
"id": "review",
"label": "Reviewed",
"value": 440
},
{
"id": "complete",
"label": "Completed",
"value": 260
}
];
<Chart type="funnel" label="Journey conversion" data={sampleFunnelParts} />Timeline
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartRange } from "@/components/ui/chart"
const sampleChartRanges: ChartRange[] = [
{
"id": "discovery",
"label": "Discovery",
"start": 0,
"end": 5,
"status": "success"
},
{
"id": "prototype",
"label": "Prototype",
"start": 4,
"end": 12,
"status": "warning"
},
{
"id": "build",
"label": "Build",
"start": 10,
"end": 24,
"status": "danger"
},
{
"id": "review",
"label": "Review",
"start": 24,
"end": 24,
"status": "neutral"
}
];
<Chart type="timeline" label="Delivery schedule" data={sampleChartRanges} range={[0, 28]} marker={{ value: 14, label: "Checkpoint" }} />Cohort retention
Original illustrative cohorts. Null means not yet observed; zero means an observed zero percent.
import { Chart } from "@/components/ui/chart"
import type { ChartCohortRow } from "@/components/ui/chart"
const sampleCohortColumns: Array<{ id: string; label: string }> = [
{
"id": "w0",
"label": "Week 0"
},
{
"id": "w1",
"label": "Week 1"
},
{
"id": "w2",
"label": "Week 2"
},
{
"id": "w3",
"label": "Week 3"
}
];
const sampleChartCohorts: ChartCohortRow[] = [
{
"id": "a",
"label": "Cohort A",
"size": 240,
"values": [
100,
72,
54,
42
]
},
{
"id": "b",
"label": "Cohort B",
"size": 280,
"values": [
100,
75,
58,
null
]
},
{
"id": "c",
"label": "Cohort C",
"size": 310,
"values": [
100,
78,
null,
null
]
},
{
"id": "d",
"label": "Cohort D",
"size": 330,
"values": [
100,
null,
null,
null
]
}
];
<Chart type="cohort" label="Weekly retention" data={sampleChartCohorts} columns={sampleCohortColumns} />Service uptime
Original equal-duration observations. Unknown periods remain explicit; summaries average known availability.
import { Chart } from "@/components/ui/chart"
import type { ChartUptimeRow } from "@/components/ui/chart"
const sampleChartUptime: ChartUptimeRow[] = [
{
"id": "gateway",
"label": "Gateway",
"samples": [
{
"id": "day-1",
"label": "Day 1",
"status": "success",
"availability": 100
},
{
"id": "day-2",
"label": "Day 2",
"status": "success",
"availability": 100
},
{
"id": "day-3",
"label": "Day 3",
"status": "success",
"availability": 100
},
{
"id": "day-4",
"label": "Day 4",
"status": "success",
"availability": 100
},
{
"id": "day-5",
"label": "Day 5",
"status": "success",
"availability": 100
},
{
"id": "day-6",
"label": "Day 6",
"status": "success",
"availability": 100
},
{
"id": "day-7",
"label": "Day 7",
"status": "success",
"availability": 100
},
{
"id": "day-8",
"label": "Day 8",
"status": "success",
"availability": 100
},
{
"id": "day-9",
"label": "Day 9",
"status": "success",
"availability": 100
},
{
"id": "day-10",
"label": "Day 10",
"status": "success",
"availability": 100
},
{
"id": "day-11",
"label": "Day 11",
"status": "success",
"availability": 100
},
{
"id": "day-12",
"label": "Day 12",
"status": "success",
"availability": 100
},
{
"id": "day-13",
"label": "Day 13",
"status": "success",
"availability": 100
},
{
"id": "day-14",
"label": "Day 14",
"status": "success",
"availability": 100
},
{
"id": "day-15",
"label": "Day 15",
"status": "success",
"availability": 100
},
{
"id": "day-16",
"label": "Day 16",
"status": "success",
"availability": 100
},
{
"id": "day-17",
"label": "Day 17",
"status": "success",
"availability": 100
},
{
"id": "day-18",
"label": "Day 18",
"status": "success",
"availability": 100
},
{
"id": "day-19",
"label": "Day 19",
"status": "success",
"availability": 100
},
{
"id": "day-20",
"label": "Day 20",
"status": "success",
"availability": 100
},
{
"id": "day-21",
"label": "Day 21",
"status": "success",
"availability": 100
},
{
"id": "day-22",
"label": "Day 22",
"status": "success",
"availability": 100
},
{
"id": "day-23",
"label": "Day 23",
"status": "success",
"availability": 100
},
{
"id": "day-24",
"label": "Day 24",
"status": "success",
"availability": 100
},
{
"id": "day-25",
"label": "Day 25",
"status": "success",
"availability": 100
},
{
"id": "day-26",
"label": "Day 26",
"status": "success",
"availability": 100
},
{
"id": "day-27",
"label": "Day 27",
"status": "success",
"availability": 100
},
{
"id": "day-28",
"label": "Day 28",
"status": "success",
"availability": 100
},
{
"id": "day-29",
"label": "Day 29",
"status": "success",
"availability": 100
},
{
"id": "day-30",
"label": "Day 30",
"status": "success",
"availability": 100
},
{
"id": "day-31",
"label": "Day 31",
"status": "success",
"availability": 100
},
{
"id": "day-32",
"label": "Day 32",
"status": "success",
"availability": 100
},
{
"id": "day-33",
"label": "Day 33",
"status": "success",
"availability": 100
},
{
"id": "day-34",
"label": "Day 34",
"status": "success",
"availability": 100
},
{
"id": "day-35",
"label": "Day 35",
"status": "success",
"availability": 100
},
{
"id": "day-36",
"label": "Day 36",
"status": "success",
"availability": 100
},
{
"id": "day-37",
"label": "Day 37",
"status": "success",
"availability": 100
},
{
"id": "day-38",
"label": "Day 38",
"status": "success",
"availability": 100
},
{
"id": "day-39",
"label": "Day 39",
"status": "success",
"availability": 100
},
{
"id": "day-40",
"label": "Day 40",
"status": "success",
"availability": 100
},
{
"id": "day-41",
"label": "Day 41",
"status": "success",
"availability": 100
},
{
"id": "day-42",
"label": "Day 42",
"status": "success",
"availability": 100
},
{
"id": "day-43",
"label": "Day 43",
"status": "success",
"availability": 100
},
{
"id": "day-44",
"label": "Day 44",
"status": "warning",
"availability": 99.2
},
{
"id": "day-45",
"label": "Day 45",
"status": "success",
"availability": 100
},
{
"id": "day-46",
"label": "Day 46",
"status": "success",
"availability": 100
},
{
"id": "day-47",
"label": "Day 47",
"status": "success",
"availability": 100
},
{
"id": "day-48",
"label": "Day 48",
"status": "success",
"availability": 100
},
{
"id": "day-49",
"label": "Day 49",
"status": "success",
"availability": 100
},
{
"id": "day-50",
"label": "Day 50",
"status": "success",
"availability": 100
},
{
"id": "day-51",
"label": "Day 51",
"status": "success",
"availability": 100
},
{
"id": "day-52",
"label": "Day 52",
"status": "success",
"availability": 100
},
{
"id": "day-53",
"label": "Day 53",
"status": "success",
"availability": 100
},
{
"id": "day-54",
"label": "Day 54",
"status": "success",
"availability": 100
},
{
"id": "day-55",
"label": "Day 55",
"status": "success",
"availability": 100
},
{
"id": "day-56",
"label": "Day 56",
"status": "success",
"availability": 100
},
{
"id": "day-57",
"label": "Day 57",
"status": "success",
"availability": 100
},
{
"id": "day-58",
"label": "Day 58",
"status": "success",
"availability": 100
},
{
"id": "day-59",
"label": "Day 59",
"status": "success",
"availability": 100
},
{
"id": "day-60",
"label": "Day 60",
"status": "success",
"availability": 100
},
{
"id": "day-61",
"label": "Day 61",
"status": "success",
"availability": 100
},
{
"id": "day-62",
"label": "Day 62",
"status": "success",
"availability": 100
},
{
"id": "day-63",
"label": "Day 63",
"status": "success",
"availability": 100
},
{
"id": "day-64",
"label": "Day 64",
"status": "success",
"availability": 100
},
{
"id": "day-65",
"label": "Day 65",
"status": "success",
"availability": 100
},
{
"id": "day-66",
"label": "Day 66",
"status": "success",
"availability": 100
},
{
"id": "day-67",
"label": "Day 67",
"status": "success",
"availability": 100
},
{
"id": "day-68",
"label": "Day 68",
"status": "success",
"availability": 100
},
{
"id": "day-69",
"label": "Day 69",
"status": "danger",
"availability": 96.8
},
{
"id": "day-70",
"label": "Day 70",
"status": "success",
"availability": 100
},
{
"id": "day-71",
"label": "Day 71",
"status": "success",
"availability": 100
},
{
"id": "day-72",
"label": "Day 72",
"status": "success",
"availability": 100
},
{
"id": "day-73",
"label": "Day 73",
"status": "success",
"availability": 100
},
{
"id": "day-74",
"label": "Day 74",
"status": "success",
"availability": 100
},
{
"id": "day-75",
"label": "Day 75",
"status": "success",
"availability": 100
},
{
"id": "day-76",
"label": "Day 76",
"status": "success",
"availability": 100
},
{
"id": "day-77",
"label": "Day 77",
"status": "success",
"availability": 100
},
{
"id": "day-78",
"label": "Day 78",
"status": "success",
"availability": 100
},
{
"id": "day-79",
"label": "Day 79",
"status": "success",
"availability": 100
},
{
"id": "day-80",
"label": "Day 80",
"status": "success",
"availability": 100
},
{
"id": "day-81",
"label": "Day 81",
"status": "success",
"availability": 100
},
{
"id": "day-82",
"label": "Day 82",
"status": "success",
"availability": 100
},
{
"id": "day-83",
"label": "Day 83",
"status": "success",
"availability": 100
},
{
"id": "day-84",
"label": "Day 84",
"status": "success",
"availability": 100
},
{
"id": "day-85",
"label": "Day 85",
"status": "success",
"availability": 100
},
{
"id": "day-86",
"label": "Day 86",
"status": "success",
"availability": 100
},
{
"id": "day-87",
"label": "Day 87",
"status": "success",
"availability": 100
},
{
"id": "day-88",
"label": "Day 88",
"status": "success",
"availability": 100
},
{
"id": "day-89",
"label": "Day 89",
"status": "success",
"availability": 100
},
{
"id": "day-90",
"label": "Day 90",
"status": "unknown",
"availability": null
}
]
},
{
"id": "queue",
"label": "Queue",
"samples": [
{
"id": "day-1",
"label": "Day 1",
"status": "success",
"availability": 100
},
{
"id": "day-2",
"label": "Day 2",
"status": "success",
"availability": 100
},
{
"id": "day-3",
"label": "Day 3",
"status": "success",
"availability": 100
},
{
"id": "day-4",
"label": "Day 4",
"status": "success",
"availability": 100
},
{
"id": "day-5",
"label": "Day 5",
"status": "success",
"availability": 100
},
{
"id": "day-6",
"label": "Day 6",
"status": "success",
"availability": 100
},
{
"id": "day-7",
"label": "Day 7",
"status": "success",
"availability": 100
},
{
"id": "day-8",
"label": "Day 8",
"status": "success",
"availability": 100
},
{
"id": "day-9",
"label": "Day 9",
"status": "success",
"availability": 100
},
{
"id": "day-10",
"label": "Day 10",
"status": "success",
"availability": 100
},
{
"id": "day-11",
"label": "Day 11",
"status": "success",
"availability": 100
},
{
"id": "day-12",
"label": "Day 12",
"status": "success",
"availability": 100
},
{
"id": "day-13",
"label": "Day 13",
"status": "success",
"availability": 100
},
{
"id": "day-14",
"label": "Day 14",
"status": "success",
"availability": 100
},
{
"id": "day-15",
"label": "Day 15",
"status": "success",
"availability": 100
},
{
"id": "day-16",
"label": "Day 16",
"status": "success",
"availability": 100
},
{
"id": "day-17",
"label": "Day 17",
"status": "success",
"availability": 100
},
{
"id": "day-18",
"label": "Day 18",
"status": "success",
"availability": 100
},
{
"id": "day-19",
"label": "Day 19",
"status": "success",
"availability": 100
},
{
"id": "day-20",
"label": "Day 20",
"status": "success",
"availability": 100
},
{
"id": "day-21",
"label": "Day 21",
"status": "success",
"availability": 100
},
{
"id": "day-22",
"label": "Day 22",
"status": "success",
"availability": 100
},
{
"id": "day-23",
"label": "Day 23",
"status": "success",
"availability": 100
},
{
"id": "day-24",
"label": "Day 24",
"status": "success",
"availability": 100
},
{
"id": "day-25",
"label": "Day 25",
"status": "success",
"availability": 100
},
{
"id": "day-26",
"label": "Day 26",
"status": "success",
"availability": 100
},
{
"id": "day-27",
"label": "Day 27",
"status": "success",
"availability": 100
},
{
"id": "day-28",
"label": "Day 28",
"status": "success",
"availability": 100
},
{
"id": "day-29",
"label": "Day 29",
"status": "success",
"availability": 100
},
{
"id": "day-30",
"label": "Day 30",
"status": "success",
"availability": 100
},
{
"id": "day-31",
"label": "Day 31",
"status": "success",
"availability": 100
},
{
"id": "day-32",
"label": "Day 32",
"status": "success",
"availability": 100
},
{
"id": "day-33",
"label": "Day 33",
"status": "success",
"availability": 100
},
{
"id": "day-34",
"label": "Day 34",
"status": "success",
"availability": 100
},
{
"id": "day-35",
"label": "Day 35",
"status": "success",
"availability": 100
},
{
"id": "day-36",
"label": "Day 36",
"status": "success",
"availability": 100
},
{
"id": "day-37",
"label": "Day 37",
"status": "success",
"availability": 100
},
{
"id": "day-38",
"label": "Day 38",
"status": "success",
"availability": 100
},
{
"id": "day-39",
"label": "Day 39",
"status": "success",
"availability": 100
},
{
"id": "day-40",
"label": "Day 40",
"status": "success",
"availability": 100
},
{
"id": "day-41",
"label": "Day 41",
"status": "success",
"availability": 100
},
{
"id": "day-42",
"label": "Day 42",
"status": "success",
"availability": 100
},
{
"id": "day-43",
"label": "Day 43",
"status": "success",
"availability": 100
},
{
"id": "day-44",
"label": "Day 44",
"status": "success",
"availability": 100
},
{
"id": "day-45",
"label": "Day 45",
"status": "success",
"availability": 100
},
{
"id": "day-46",
"label": "Day 46",
"status": "success",
"availability": 100
},
{
"id": "day-47",
"label": "Day 47",
"status": "success",
"availability": 100
},
{
"id": "day-48",
"label": "Day 48",
"status": "success",
"availability": 100
},
{
"id": "day-49",
"label": "Day 49",
"status": "success",
"availability": 100
},
{
"id": "day-50",
"label": "Day 50",
"status": "success",
"availability": 100
},
{
"id": "day-51",
"label": "Day 51",
"status": "success",
"availability": 100
},
{
"id": "day-52",
"label": "Day 52",
"status": "success",
"availability": 100
},
{
"id": "day-53",
"label": "Day 53",
"status": "success",
"availability": 100
},
{
"id": "day-54",
"label": "Day 54",
"status": "warning",
"availability": 99.6
},
{
"id": "day-55",
"label": "Day 55",
"status": "success",
"availability": 100
},
{
"id": "day-56",
"label": "Day 56",
"status": "success",
"availability": 100
},
{
"id": "day-57",
"label": "Day 57",
"status": "success",
"availability": 100
},
{
"id": "day-58",
"label": "Day 58",
"status": "success",
"availability": 100
},
{
"id": "day-59",
"label": "Day 59",
"status": "success",
"availability": 100
},
{
"id": "day-60",
"label": "Day 60",
"status": "success",
"availability": 100
},
{
"id": "day-61",
"label": "Day 61",
"status": "success",
"availability": 100
},
{
"id": "day-62",
"label": "Day 62",
"status": "success",
"availability": 100
},
{
"id": "day-63",
"label": "Day 63",
"status": "success",
"availability": 100
},
{
"id": "day-64",
"label": "Day 64",
"status": "success",
"availability": 100
},
{
"id": "day-65",
"label": "Day 65",
"status": "success",
"availability": 100
},
{
"id": "day-66",
"label": "Day 66",
"status": "success",
"availability": 100
},
{
"id": "day-67",
"label": "Day 67",
"status": "success",
"availability": 100
},
{
"id": "day-68",
"label": "Day 68",
"status": "success",
"availability": 100
},
{
"id": "day-69",
"label": "Day 69",
"status": "success",
"availability": 100
},
{
"id": "day-70",
"label": "Day 70",
"status": "success",
"availability": 100
},
{
"id": "day-71",
"label": "Day 71",
"status": "success",
"availability": 100
},
{
"id": "day-72",
"label": "Day 72",
"status": "success",
"availability": 100
},
{
"id": "day-73",
"label": "Day 73",
"status": "success",
"availability": 100
},
{
"id": "day-74",
"label": "Day 74",
"status": "success",
"availability": 100
},
{
"id": "day-75",
"label": "Day 75",
"status": "success",
"availability": 100
},
{
"id": "day-76",
"label": "Day 76",
"status": "success",
"availability": 100
},
{
"id": "day-77",
"label": "Day 77",
"status": "success",
"availability": 100
},
{
"id": "day-78",
"label": "Day 78",
"status": "success",
"availability": 100
},
{
"id": "day-79",
"label": "Day 79",
"status": "success",
"availability": 100
},
{
"id": "day-80",
"label": "Day 80",
"status": "success",
"availability": 100
},
{
"id": "day-81",
"label": "Day 81",
"status": "success",
"availability": 100
},
{
"id": "day-82",
"label": "Day 82",
"status": "success",
"availability": 100
},
{
"id": "day-83",
"label": "Day 83",
"status": "success",
"availability": 100
},
{
"id": "day-84",
"label": "Day 84",
"status": "success",
"availability": 100
},
{
"id": "day-85",
"label": "Day 85",
"status": "success",
"availability": 100
},
{
"id": "day-86",
"label": "Day 86",
"status": "success",
"availability": 100
},
{
"id": "day-87",
"label": "Day 87",
"status": "success",
"availability": 100
},
{
"id": "day-88",
"label": "Day 88",
"status": "success",
"availability": 100
},
{
"id": "day-89",
"label": "Day 89",
"status": "success",
"availability": 100
},
{
"id": "day-90",
"label": "Day 90",
"status": "success",
"availability": 100
}
]
}
];
<Chart type="uptime" label="Daily service availability" data={sampleChartUptime} />Current and prior periods
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleComparisonSeries: ChartSeries[] = [
{
"id": "current",
"label": "Current period"
},
{
"id": "prior",
"label": "Prior period",
"comparison": true
}
];
const sampleComparisonRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"current": 280,
"prior": 240
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"current": 340,
"prior": 270
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"current": 310,
"prior": 300
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"current": 420,
"prior": 330
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"current": 390,
"prior": 360
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"current": 480,
"prior": 390
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"current": 520,
"prior": 420
}
}
];
<Chart type="line" label="Current and prior activity" data={sampleComparisonRows} series={sampleComparisonSeries} />Missing values
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleMissingRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": null,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="line" label="Activity with an observation gap" data={sampleMissingRows} series={sampleChartSeries} />Signed values
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartRow, ChartSeries } from "@/components/ui/chart"
const sampleSignedRows: ChartRow[] = [
{
"id": "a",
"label": "North",
"x": 0,
"values": {
"visits": 80,
"readers": -30
}
},
{
"id": "b",
"label": "South",
"x": 1,
"values": {
"visits": -40,
"readers": 65
}
},
{
"id": "c",
"label": "East",
"x": 2,
"values": {
"visits": 50,
"readers": -20
}
}
];
const sampleSignedSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
}
];
<Chart type="bar" label="Regional net changes" data={sampleSignedRows} series={sampleSignedSeries} layout="stacked" />Empty total
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartItem } from "@/components/ui/chart"
const sampleZeroParts: ChartItem[] = [
{
"id": "pending",
"label": "Awaiting activity",
"value": 0
}
];
<Chart type="donut" label="Activity awaiting observations" data={sampleZeroParts} />Eight series
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleEightSeries: ChartSeries[] = [
{
"id": "series-0",
"label": "Group 1"
},
{
"id": "series-1",
"label": "Group 2"
},
{
"id": "series-2",
"label": "Group 3"
},
{
"id": "series-3",
"label": "Group 4"
},
{
"id": "series-4",
"label": "Group 5"
},
{
"id": "series-5",
"label": "Group 6"
},
{
"id": "series-6",
"label": "Group 7"
},
{
"id": "series-7",
"label": "Group 8"
}
];
const sampleEightRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"series-0": 20,
"series-1": 35,
"series-2": 50,
"series-3": 65,
"series-4": 80,
"series-5": 95,
"series-6": 110,
"series-7": 125
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"series-0": 23,
"series-1": 39,
"series-2": 55,
"series-3": 71,
"series-4": 87,
"series-5": 103,
"series-6": 119,
"series-7": 135
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"series-0": 26,
"series-1": 43,
"series-2": 60,
"series-3": 77,
"series-4": 94,
"series-5": 111,
"series-6": 128,
"series-7": 145
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"series-0": 29,
"series-1": 47,
"series-2": 65,
"series-3": 83,
"series-4": 101,
"series-5": 119,
"series-6": 137,
"series-7": 155
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"series-0": 32,
"series-1": 51,
"series-2": 70,
"series-3": 89,
"series-4": 108,
"series-5": 127,
"series-6": 146,
"series-7": 125
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"series-0": 35,
"series-1": 55,
"series-2": 75,
"series-3": 95,
"series-4": 115,
"series-5": 95,
"series-6": 115,
"series-7": 135
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"series-0": 38,
"series-1": 59,
"series-2": 80,
"series-3": 101,
"series-4": 82,
"series-5": 103,
"series-6": 124,
"series-7": 145
}
}
];
<Chart type="line" label="Eight labeled groups" data={sampleEightRows} series={sampleEightSeries} />Pending refresh
Original illustrative data stays visible while only the plot dims.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleChartRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": 420,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
<Chart type="line" label="Activity being refreshed" data={sampleChartRows} series={sampleChartSeries} pending />Localized labels
Original illustrative data. Copy includes the complete local setup.
import { Chart } from "@/components/ui/chart"
import type { ChartSeries, ChartRow, ChartLabels } from "@/components/ui/chart"
const sampleChartSeries: ChartSeries[] = [
{
"id": "visits",
"label": "Visits"
},
{
"id": "readers",
"label": "Readers"
},
{
"id": "members",
"label": "Members"
}
];
const sampleMissingRows: ChartRow[] = [
{
"id": "mon",
"label": "Monday",
"x": 1791763200000,
"values": {
"visits": 280,
"readers": 180,
"members": 90
}
},
{
"id": "tue",
"label": "Tuesday",
"x": 1791849600000,
"values": {
"visits": 340,
"readers": 220,
"members": 110
}
},
{
"id": "wed",
"label": "Wednesday",
"x": 1791936000000,
"values": {
"visits": 310,
"readers": 200,
"members": 120
}
},
{
"id": "thu",
"label": "Thursday",
"x": 1792022400000,
"values": {
"visits": null,
"readers": 270,
"members": 150
}
},
{
"id": "fri",
"label": "Friday",
"x": 1792108800000,
"values": {
"visits": 390,
"readers": 260,
"members": 170
}
},
{
"id": "sat",
"label": "Saturday",
"x": 1792195200000,
"values": {
"visits": 480,
"readers": 310,
"members": 190
}
},
{
"id": "sun",
"label": "Sunday",
"x": 1792281600000,
"values": {
"visits": 520,
"readers": 340,
"members": 220
}
}
];
const sampleChartLabels: Partial<ChartLabels> = {
"viewData": "Open values",
"hideData": "Close values",
"missing": "Not measured",
"unobserved": "Not yet observed"
};
<Chart type="line" label="Activity with custom labels" data={sampleMissingRows} series={sampleChartSeries} locale="en-GB" labels={sampleChartLabels} />Nên và không nên
Nên
- Use the ten discriminated data contracts. Keep ids stable and row labels complete.
- Use series in chartPalette order; mark comparisons with comparison=true and supply direct labels or patterns for more than four series.
- Put values and labels on neutral surfaces. Compose metrics with the full DataTrend block and goals with Progress.
- Keep prior content while refreshing. Use a delayed Skeleton only for a first load.
- Label sample datasets as illustrative and derive every chart, metric and table on a screen from the same rows.
Không nên
- Do not pick arbitrary hues, apply color alpha, add opacity steps or animate chart drawing.
- Do not connect across missing values, clamp invalid facts or treat null as zero.
- Do not average unequal-duration availability samples or count status cells as uptime.
- Do not imply that cohort heat bands are success thresholds.
- Do not add a second Card surface around a chart already inside a Card.
Props
| Tên | Kiểu | Giá trị | Mặc định | Mô tả |
|---|---|---|---|---|
| type bắt buộc | enum | line | area | bar | sparkline | composition | donut | funnel | timeline | cohort | uptime | - | Required discriminant. Each type accepts only its own data shape. |
| label bắt buộc | string | - | - | Required accessible chart name. |
| description | string | - | - | Optional context associated with the chart. |
| data bắt buộc | ChartRow[] | ChartItem[] | ChartRange[] | ChartCohortRow[] | ChartUptimeRow[] | - | - | Ordered local data matching type. Null preserves missing or unobserved meaning; invalid values are reported. |
| series | ChartSeries[] | - | - | Required for line, area, bar and sparkline. Stable ids map to values; comparison adds a dashed stroke. Sparkline takes one series. |
| height | number | - | - | Plot height in CSS pixels. Defaults to 256, sparkline 48, compact bar 32. Timeline, cohort and uptime size to their rows by default; a height fixes the timeline and caps cohort and uptime, which then scroll. |
| legend | boolean | - | true | Show the series or status legend. Defaults true except sparkline and single-series bar. Composition, donut and funnel keep direct labels without a duplicate legend. |
| interactive | boolean | - | true | Enable pointer, touch and keyboard inspection. Defaults true except sparkline. |
| pending | boolean | - | false | Retain current data, mark the figure busy and dim only the plot. |
| table | enum | toggle | visible | hidden | toggle | Toggle reveals the semantic data view. Hidden keeps the table accessible with visually hidden presentation. Sparkline defaults hidden. |
| locale | string | - | en | Explicit number-formatting locale shared by server and client. |
| labels | Partial<ChartLabels> | - | - | Override viewData, hideData, loading, empty, missing, unobserved, invalid, noSeries, zeroTotal, value, total, cohortSize, conversion, share, coverage, success, warning, danger, unknown, neutral, start, end, status and point text. Raw values use formatValue; derived percentages always use locale-aware percentage formatting. |
| formatValue | (value: number, id: string) => string | - | - | Format a finite number and stable series or item id without changing geometry. |
| xScale | enum | category | linear | time | category | Cartesian axis spacing. Numeric and time modes require finite, strictly ascending x values; time uses epoch milliseconds. Without formatX, time positions show a short UTC date. |
| formatX | (value: number) => string | - | - | Format numeric or time ticks for Cartesian charts and timeline; full row labels remain available. |
| domain | [number, number] | - | - | Cartesian finite ascending value bounds containing every value. Bar domains must include zero. |
| axes | boolean | - | true | Show Cartesian axes. Defaults true except sparkline and compact bar. |
| grid | boolean | - | true | Show Cartesian grid lines. Defaults true except sparkline and compact bar. |
| hiddenSeries | string[] | - | - | Controlled hidden Cartesian series ids. Palette positions remain stable. |
| defaultHiddenSeries | string[] | - | - | Uncontrolled initial hidden Cartesian series ids. |
| onHiddenSeriesChange | (ids: string[]) => void | - | - | Receive the hidden series ids after a legend action. |
| stack | enum | none | normal | none | Area only: overlaid independent series or a nonnegative summed stack. Null breaks the stack at that row. |
| orientation | enum | vertical | horizontal | vertical | Bar only: vertical or horizontal bars. |
| layout | enum | grouped | stacked | percentage | grouped | Bar only: grouped, signed stacked or nonnegative percentage composition. Percentage rows with zero totals stay empty. |
| compact | boolean | - | false | Bar only: short numeric cell display without axes or legend. A shared domain gives comparable lengths. |
| range | [number, number] | - | - | Timeline only, required finite ascending range in caller-defined units. Every entry must fit. |
| marker | { value: number; label: string } | - | - | Optional timeline reference position. Outside-range positions remain described without a visual marker. |
| columns | Array<{ id: string; label: string }> | - | - | Cohort only, required unique columns. Each row has one percentage or null per column. |
| thresholds | [number, number, number, number] | - | - | Cohort only: four ascending bounds inside (0, 100), defining five ordered heat bands of chart series 1 that grow stronger with each band; the value prints on the cell. Defaults [20, 40, 60, 80]. |
Cấu tạo
| Phần | Mô tả |
|---|---|
| root | Named figure with description and loading state. |
| plot | Responsive plot and one keyboard inspection surface. Lines and area edges are smooth monotone curves that never overshoot a value; area fills fade from the series color at opacity-subtle to transparent. Grid lines are dashed and quiet; the zero line turns solid on signed domains. Bars are slim, round only their value end and never get outlines. Composition parts and donut sectors are separated by a 2px gap instead of an outline. Inspected line and area points use their series fill, a white 2px color-border-chart-marker ring and drop-shadow-low. The inspected composition part grows 4px above and below the track, and the inspected donut sector grows 4px outward, drawn above its neighbors. |
| legend | Series visibility buttons with compact keys (a short stroke for lines, a small swatch for filled marks) or a static status list with status icons. Composition and donut list each category with its amount and share; funnel rows show the conversion from the previous stage, the amount and the share of the first stage, and every stage uses series 1, since stages are one measure. |
| tooltip | Compact inspected values beside the pointer or keyboard-selected mark, bounded inside the plot and rounded with radius-container. |
| table | Semantic raw-data view with caption and headers. |
Khả năng truy cập
Role: figure
| Phím | Hành động |
|---|---|
| Tab | Enter the plot once; legend buttons and data toggle remain separate controls. |
| Arrow keys | Inspect rows and visible series; navigate ranges or matrix cells according to chart type. |
| Home / End | Inspect the first or last Cartesian row. |
| Escape | Close inspection and restore focus to the plot. |
- The required label names the figure; description supplies context. Every chart retains a semantic data table, including table=hidden.
- Null means missing for Cartesian values and not yet observed for cohorts. Zero is an observed value.
- Series retain palette identity when hidden. More than four series add patterns and dashes; with four or fewer, keep the legend or the data table visible, since a hidden legend leaves color as the only cue.
- Touch taps pin inspection; a second tap or outside tap dismisses it. Normal page scrolling remains available. Mouse hover never receives keyboard focus contours, and a focused plot keeps its focus ring while the mouse moves. Each bar group is one hit band across the value axis; the gaps between groups dismiss inspection. Uptime rows are 44px targets that pick the period under the pointer. In horizontal bars, Up and Down move between rows and Left and Right between series.
- Uptime samples represent equal-duration periods. Coverage and the mean of known availability remain distinct.
Cài đặt
npx werewolf-ui add chartChạy npx werewolf-ui init một lần trong app trước khi thêm component. Init cài token, thêm CSS import và luật cho agent. Add cài component này cùng các dependency và giữ nguyên theme của bạn. Xem Cài đặt để biết yêu cầu và cách cài qua registry.