Compares a value across categories with bars from a zero baseline.
Chart tabs
One chart frame with a segmented control that switches between several views of the same data, morphing between views that share a chart type.
- Use when
- The same entities under two to five measures or scalings where each view changes the reading: total / per capita / change, absolute / share, linear / log. Give the frame a plain label as its title. Each view's
subtitlenames its measure. - Avoid when
- Hiding the most important view behind a tab (show it first, or show both with small multiple grid); unrelated charts (give each its own figure); more than five views.
Preview
CO2 emissions of six large emitters, 2023
CO2 emissions from fossil fuels, billion tonnes, 2023
Source: Global Carbon Budget 2024 · Rounded, approximate figures for illustration
import { ChartTabs, registerAll } from "insightcharts";
// The slot props below are JSON specs. This makes their `type` names resolvable.
registerAll();
export function Example() {
return (
<ChartTabs
title="CO2 emissions of six large emitters, 2023"
tabsPosition="below"
chart={{
type: "bar-chart",
data: [
{ country: "China", total: 11.9, perCapita: 8.4, change: 0.38 },
{ country: "United States", total: 4.9, perCapita: 14.3, change: -0.13 },
{ country: "India", total: 3.1, perCapita: 2.1, change: 0.74 },
{ country: "Russia", total: 1.8, perCapita: 12.5, change: 0.1 },
{ country: "Japan", total: 1, perCapita: 8, change: -0.19 },
{ country: "Germany", total: 0.6, perCapita: 7.1, change: -0.28 },
],
x: "country",
y: "total",
sort: "desc",
orientation: "horizontal",
height: 280,
highlight: "China",
format: "{value} Gt",
subtitle: "CO2 emissions from fossil fuels, billion tonnes, 2023",
}}
views={[
{ label: "Total", id: "total" },
{
label: "Per capita",
id: "per-capita",
props: {
y: "perCapita",
highlight: "United States",
format: "{value} t",
subtitle: "CO2 emissions per person, tonnes, 2023",
},
},
{
label: "Change since 2010",
id: "change",
props: {
y: "change",
highlight: "India",
format: "percent",
subtitle: "Change in CO2 emissions, 2010 to 2023",
},
},
]}
source="Global Carbon Budget 2024"
note="Rounded, approximate figures for illustration"
/>
);
}{
"type": "chart-tabs",
"title": "CO2 emissions of six large emitters, 2023",
"tabsPosition": "below",
"chart": {
"type": "bar-chart",
"data": [
{ "country": "China", "total": 11.9, "perCapita": 8.4, "change": 0.38 },
{ "country": "United States", "total": 4.9, "perCapita": 14.3, "change": -0.13 },
{ "country": "India", "total": 3.1, "perCapita": 2.1, "change": 0.74 },
{ "country": "Russia", "total": 1.8, "perCapita": 12.5, "change": 0.1 },
{ "country": "Japan", "total": 1, "perCapita": 8, "change": -0.19 },
{ "country": "Germany", "total": 0.6, "perCapita": 7.1, "change": -0.28 }
],
"x": "country",
"y": "total",
"sort": "desc",
"orientation": "horizontal",
"height": 280,
"highlight": "China",
"format": "{value} Gt",
"subtitle": "CO2 emissions from fossil fuels, billion tonnes, 2023"
},
"views": [
{ "label": "Total", "id": "total" },
{
"label": "Per capita",
"id": "per-capita",
"props": {
"y": "perCapita",
"highlight": "United States",
"format": "{value} t",
"subtitle": "CO2 emissions per person, tonnes, 2023"
}
},
{
"label": "Change since 2010",
"id": "change",
"props": {
"y": "change",
"highlight": "India",
"format": "percent",
"subtitle": "Change in CO2 emissions, 2010 to 2023"
}
}
],
"source": "Global Carbon Budget 2024",
"note": "Rounded, approximate figures for illustration"
}Render with import { Insight } from "insightcharts" and <Insight spec={spec} />. Nested specs resolve by name; nothing else to import.
Composition
Built from
The pieces chart tabs renders or expects in its slots.
Atoms
2Shows how one or more values change over time or another ordered dimension.
Used in
No template lists chart tabs in its composes. It still fits any slot that takes a component.
Installation
$ pnpm dlx shadcn@latest add @insightcharts/chart-tabsThe CLI copies the source into your project and needs the @insightcharts registry in components.json; see installation. With the package, import it by name:
import { ChartTabs } from "insightcharts";Examples
Tabs beside the title, a different chart per view
Solar supplied 11.1% of EU electricity in 2024
Solar and coal share of EU electricity generation, 2019 to 2024
Source: Ember · Figures are approximate, for illustration
import { ChartTabs, registerAll } from "insightcharts";
// The slot props below are JSON specs. This makes their `type` names resolvable.
registerAll();
export function Example() {
return (
<ChartTabs
title="Solar supplied 11.1% of EU electricity in 2024"
defaultView="Trend"
views={[
{
label: "Trend",
chart: {
type: "line-chart",
data: [
{ year: "2019", Solar: 4.2, Coal: 15 },
{ year: "2020", Solar: 5, Coal: 13 },
{ year: "2021", Solar: 5.4, Coal: 14.7 },
{ year: "2022", Solar: 7, Coal: 15.8 },
{ year: "2023", Solar: 9.1, Coal: 12.3 },
{ year: "2024", Solar: 11.1, Coal: 9.8 },
],
x: "year",
y: ["Solar", "Coal"],
format: "{value}%",
height: 260,
subtitle: "Solar and coal share of EU electricity generation, 2019 to 2024",
},
},
{
label: "2024",
chart: {
type: "bar-chart",
data: [
{ source: "Solar", share: 11.1 },
{ source: "Coal", share: 9.8 },
],
x: "source",
y: "share",
format: "{value}%",
height: 260,
highlight: "Solar",
subtitle: "Share of EU electricity generation, 2024. Coal supplied 9.8%.",
},
},
]}
source="Ember"
note="Figures are approximate, for illustration"
/>
);
}{
"type": "chart-tabs",
"title": "Solar supplied 11.1% of EU electricity in 2024",
"defaultView": "Trend",
"views": [
{
"label": "Trend",
"chart": {
"type": "line-chart",
"data": [
{ "year": "2019", "Solar": 4.2, "Coal": 15 },
{ "year": "2020", "Solar": 5, "Coal": 13 },
{ "year": "2021", "Solar": 5.4, "Coal": 14.7 },
{ "year": "2022", "Solar": 7, "Coal": 15.8 },
{ "year": "2023", "Solar": 9.1, "Coal": 12.3 },
{ "year": "2024", "Solar": 11.1, "Coal": 9.8 }
],
"x": "year",
"y": ["Solar", "Coal"],
"format": "{value}%",
"height": 260,
"subtitle": "Solar and coal share of EU electricity generation, 2019 to 2024"
}
},
{
"label": "2024",
"chart": {
"type": "bar-chart",
"data": [
{ "source": "Solar", "share": 11.1 },
{ "source": "Coal", "share": 9.8 }
],
"x": "source",
"y": "share",
"format": "{value}%",
"height": 260,
"highlight": "Solar",
"subtitle": "Share of EU electricity generation, 2024. Coal supplied 9.8%."
}
}
],
"source": "Ember",
"note": "Figures are approximate, for illustration"
}Render with import { Insight } from "insightcharts" and <Insight spec={spec} />. Nested specs resolve by name; nothing else to import.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| chart | InsightSpec | The base chart spec every view starts from: { type, data, ... }. | |
| viewsrequired | { label, id?, props?, chart? }[] | Two to five views. props are merged over chart; or give a view its own complete chart slot. | |
| defaultView | string | number | The view shown first: an id, a label or an index. | |
| view | string | number | Controlled active view. | |
| onViewChange | (id, index) => void | Called when the reader switches view. | |
| tabsLabel | string | "Chart view" | Accessible name of the tab list. |
| tabsPosition | "right" | "below" | "right" | Tabs beside the title or under it. Under 560px they always go underneath. |
| title | string | A plain label or fact that is true of every view. | |
| subtitle | string | What the views share; each view's own subtitle names its measure. | |
| source | string | Shown under the chart as "Source: ...". | |
| note | string | Method note or caveat. | |
| children | ReactNode | Extra content under the chart. | |
| theme | ThemeInput | Theme override, passed on to the chart. | |
| mode | "auto" | "system" | "light" | "dark" | "auto" | Colour mode. |