Chart
Anatomy
Section titled “Anatomy”<Chart> <DonutChart /> <Legend> <LegendItem /> <LegendItem /> </Legend></Chart>Chart: Wraps and provides shared context (colors, currently hovered item, etc.) to child components. Not required if using a display-only chart without user interactions.DonutChart: Displays data as parts of a whole, with an optional center value and label. Currently the only chart type available in Stylus.Legend: Displays a list of labels and values related to the chart.
import { Chart, DonutChart, Legend, LegendItem } from "stylus-ui/Chart";
const data = [ { name: "Notion", amount: 281 }, { name: "VS Code", amount: 142 }, { name: "Slack", amount: 50 },];
export default () => ( <Chart className="flex items-center gap-8" data={data} category="name"> <DonutChart value="amount" /> <Legend className="w-48"> {data.map((item) => ( <LegendItem key={item.name} dataKey={item.name} label={item.name} value={item.amount} /> ))} </Legend> </Chart>);Donut chart
Section titled “Donut chart”For the simplest display, you can use DonutChart standalone, without the Chart wrapper.
import { DonutChart } from "stylus-ui/Chart";
const data = [ { name: "Notion", amount: 281 }, { name: "VS Code", amount: 142 }, { name: "Slack", amount: 50 },];
export default () => ( <DonutChart category="name" value="amount" data={data} className="size-16" />);Colors
Section titled “Colors”Each segment will automatically take on a color from the default palette. The available colors are brand, blue, green, teal, yellow, pink, fuchsia, purple, red, cyan, orange, and slate.
Specific colors only
Section titled “Specific colors only”By default, the chart cycles through all available colors in order. To use a specific subset of colors, pass an array of names to the colors prop:
import { DonutChart } from "stylus-ui/Chart";
const data = [ { name: "Primary", value: 40 }, { name: "Secondary", value: 30 }, { name: "Tertiary", value: 20 }, { name: "Other", value: 10 },];
export default () => ( <DonutChart category="name" value="value" data={data} colors={["brand", "pink", "cyan", "slate"]} />);Display value
Section titled “Display value”Display a sum of all chart segments in the center by setting showValue to true.
import { DonutChart } from "stylus-ui/Chart";import { formatIntlNumber } from "scribe-web-shared/functions";
const data = [ { name: "Notion", amount: 2814 }, { name: "VS Code", amount: 142 }, { name: "Slack", amount: 503 },];
export default () => ( <DonutChart category="name" value="amount" data={data} showValue />);Long values will automaically shrink to fit.
import { DonutChart } from "stylus-ui/Chart";import { formatIntlNumber } from "scribe-web-shared/functions";
const data = [ { name: "Notion", revenue: 4500600 }, { name: "VS Code", revenue: 3200800 }, { name: "Slack", revenue: 1800900 },];
export default () => ( <DonutChart category="name" value="revenue" data={data} showValue />);Formatting values
Section titled “Formatting values”Use the valueFormatter prop to format the display value. For example, you can use the formatIntlNumber helper to display locale-appropriate thousands separators for long numbers.
import { DonutChart } from "stylus-ui/Chart";import { formatIntlNumber } from "scribe-web-shared/functions";
const data = [ { name: "Notion", amount: 2814 }, { name: "VS Code", amount: 142 }, { name: "Slack", amount: 503 },];
export default () => ( <DonutChart category="name" value="amount" data={data} showValue valueFormatter={(v) => formatIntlNumber(v)} />);With label
Section titled “With label”To display text above the value, set label.
import { DonutChart } from "stylus-ui/Chart";import { formatIntlNumber } from "scribe-web-shared/functions";
const data = [ { name: "Notion", hours: 281 }, { name: "VS Code", hours: 142 }, { name: "Slack", hours: 50 },];
export default () => ( <DonutChart category="name" value="hours" data={data} showValue valueFormatter={(v) => `${formatIntlNumber(v)} hrs`} label="Yearly average" />);No data
Section titled “No data”When there’s no data or all values are zero, the chart displays a full ring with a - in the center:
import { DonutChart } from "stylus-ui/Chart";
export default () => ( <DonutChart category="name" value="amount" data={[]} showValue label="Yearly average" />);With legend
Section titled “With legend”Combine the DonutChart with the Legend component for interactive data visualization. The Chart wrapper automatically synchronizes hover and click states between components with zero boilerplate:
import React from "react";import { Chart, DonutChart, Legend, LegendItem } from "stylus-ui/Chart";
const data = [ { name: "Notion", amount: 281 }, { name: "VS Code", amount: 142 }, { name: "GitHub", amount: 87 }, { name: "Slack", amount: 50 }, { name: "Figma", amount: 43 },];
export default () => { const total = data.reduce((sum, item) => sum + item.amount, 0);
return ( <Chart className="flex items-center gap-8" data={data} category="name"> <DonutChart value="amount" label="Yearly average" valueFormatter={(v) => `${v} hrs`} showValue /> <Legend> {data.map((item) => ( <LegendItem key={item.name} dataKey={item.name} label={item.name} value={`${item.amount} hrs (${((item.amount / total) * 100).toFixed(1)}%)`} /> ))} </Legend> </Chart> );};With click interactions
Section titled “With click interactions”Add click handling to toggle selection by providing an onClick callback to the Chart component:
import React from "react";import { Chart, DonutChart, Legend, LegendItem } from "stylus-ui/Chart";
const data = [ { name: "Notion", amount: 281 }, { name: "VS Code", amount: 142 }, { name: "GitHub", amount: 87 }, { name: "Slack", amount: 50 }, { name: "Figma", amount: 43 },];
export default () => { const [selected, setSelected] = React.useState(null); const total = data.reduce((sum, item) => sum + item.amount, 0);
return ( <Chart className="flex items-center gap-8" data={data} category="name" selectedDataKey={selected} onClick={setSelected} > <DonutChart value="amount" label="Yearly average" valueFormatter={(v) => `${v} hrs`} showValue /> <Legend> {data.map((item) => ( <LegendItem key={item.name} dataKey={item.name} label={item.name} value={`${item.amount} hrs (${((item.amount / total) * 100).toFixed(1)}%)`} /> ))} </Legend> </Chart> );};With icons and logos
Section titled “With icons and logos”Each legend item accepts an icon prop for FontAwesome icons or a logo prop (with name and src) to display a favicon.
import React from "react";import { Chart, DonutChart, Legend, LegendItem } from "stylus-ui/Chart";import { getFavicon } from "stylus-ui/utils/getFavicon";import { faGrid2 } from "@fortawesome/pro-regular-svg-icons";
const data = [ { name: "Notion", url: "https://notion.so", amount: 281 }, { name: "Slack", url: "https://slack.com", amount: 142 }, { name: "Figma", url: "https://figma.com", amount: 87 }, { name: "Others", amount: 50 },];
export default () => { const total = data.reduce((sum, item) => sum + item.amount, 0);
return ( <Chart className="flex items-center gap-8" data={data} category="name" colors={["brand", "pink", "cyan", "slate"]} > <DonutChart value="amount" label="Yearly average" valueFormatter={(v) => `${v} hrs`} showValue /> <Legend> {data.map((item) => { const logoObj = item.url && { name: item.name, src: getFavicon({ url: item.url }), };
return ( <LegendItem key={item.name} dataKey={item.name} logo={logoObj} icon={!item.url ? faGrid2 : undefined} label={item.name} value={`${((item.amount / total) * 100).toFixed(1)}%`} /> ); })} </Legend> </Chart> );};API Reference
Section titled “API Reference”useChartContext
Section titled “useChartContext”Hook to access chart interaction context. Returns null if used outside of a Chart provider. Components can use this to sync their interaction state automatically.
Chart wrapper component that provides interaction state management and color coordination for child components. Automatically synchronizes hover, click states, and colors between DonutChart, Legend, and other chart components.
children
Child components (DonutChart, Legend, etc.)
category
The key in data objects to use as category names. Required when data is provided.
colors
Array of color keys to use for chart segments. Defaults to all available chart colors.
data
Array of data objects. When provided with category, enables automatic color coordination between child components.
hoveredDataKey
Controlled hover state (dataKey of the hovered item). When provided, the component operates in controlled mode.
onClick
Callback fired when an item is clicked. Use this for controlled selection state.
onHover
Callback fired when an item is hovered. Use this for controlled hover state.
selectedDataKey
Controlled selection state (dataKey of the selected item). When provided, the component operates in controlled mode.
DonutChart
Section titled “DonutChart”A donut chart component for visualizing proportional data with an optional center label. Automatically syncs with Chart context when used inside a Chart component.
value
The key in data objects to use as values (e.g., ‘amount’, ‘count’)
category
The key in data objects to use as category names (e.g., ‘name’, ‘app’). If not provided, will use category from Chart context.
colors
Array of color keys to use for chart segments. Defaults to all available chart colors.
data
Array of data objects to display in the chart. Each object should have properties matching the category and value keys. If not provided, will use data from Chart context.
label
Optional label text to display above the center value
labelFontSize
Optional font size for the label text (in SVG viewBox units). Default: 15
showValue
Whether to hide the center value label
valueFontSize
Optional font size for the center value text (in SVG viewBox units).
valueFormatter
Function to format the center label value. Receives the total sum of all values.
Legend
Section titled “Legend”A legend component for charts that displays colored indicators with labels and values. Automatically syncs with Chart context when used inside a Chart component.
children
Child LegendItem components to display
LegendItem
Section titled “LegendItem”A single item in a Legend component. Must be used as a child of Legend. Automatically syncs with Chart context when available.
dataKey
Unique dataKey for the legend item. Used for tracking active/highlighted state and syncing with chart data.
label
The label text to display (e.g., “Notion”, “Slack”, “Revenue”)
value
The value text to display (e.g., “35%”, “1,234”, “$50K”)
icon
Optional icon to display before the label
labelClassName
Optional className to apply to the label text
logo
Optional logo to display before the label
onClick
Callback fired when clicking the legend item. Receives the item dataKey.