import { BarChart } from "semiotic"
BarChart visualizes categorical data using rectangular bars whose lengths are proportional to the values they represent. Pass your data, specify the category and value accessors, and get a publication-ready chart with hover interactions, axes, and optional sorting — all with sensible defaults.
Quick Start
The simplest bar chart requires just data. The defaults expect each object to have category andvalue fields.
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: [ { category: "Electronics", value: 12400 }, { category: "Clothing", value: 8700 }, { category: "Grocery", value: 15300 }, // ...more data points ], /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Customize --- */ categoryLabel: "Department", valueLabel: "Sales ($)" } export default () => { return <BarChart {...frameProps} /> }
Examples
Horizontal Bars
Set orientation to "horizontal" for horizontal bars. This works well when category labels are long.
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: sampleData, /* --- Layout --- */ orientation: "horizontal", /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Customize --- */ categoryLabel: "Department", valueLabel: "Sales ($)" } export default () => { return <BarChart {...frameProps} /> }
Sorted Bars with Color
Use sort to order bars by value and colorByto color them by a data field.
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: [ { category: "Electronics", value: 12400, region: "North" }, { category: "Clothing", value: 8700, region: "South" }, // ...data with region field for coloring ], /* --- Layout --- */ sort: "desc", /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Customize --- */ colorBy: "region", categoryLabel: "Department", valueLabel: "Sales ($)" } export default () => { return <BarChart {...frameProps} /> }
Pass a valueFormat function to control how value axis tick labels are displayed.
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: sampleData, /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Customize --- */ showGrid: true, categoryLabel: "Department", valueLabel: "Sales", valueFormat: d => `${(d / 1000).toFixed(0)}k` } export default () => { return <BarChart {...frameProps} /> }
Custom Tick Labels (ReactNode)
categoryFormat can return a React element for custom tick rendering. Non-string returns render inside <foreignObject>.
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: sampleData, /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Other --- */ categoryFormat: (label) => <span style={{ fontWeight: "bold", color: "#e45050" }}>{label.toUpperCase()}</span> } export default () => { return <BarChart {...frameProps} /> }
Hover Highlight
Set hoverHighlight="series" with colorBy to dim non-hovered categories when hovering a bar.
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: colorData, /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Customize --- */ colorBy: "category", /* --- Other --- */ hoverHighlight: "series" } export default () => { return <BarChart {...frameProps} /> }
Rounded Top Corners
Use roundedTop to round only the top corners of each bar (the end away from the baseline). The bottom stays flush with the axis.
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: sampleData, /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Other --- */ roundedTop: 6 } export default () => { return <BarChart {...frameProps} /> }
JSX
<BarChart data={sampleData} categoryAccessor="category" valueAccessor="value" roundedTop={6} />
Works with horizontal bars too — the rounded end points away from the value axis:
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: sampleData, /* --- Size --- */ margin: { left: 100, top: 20, right: 20, bottom: 30 }, /* --- Layout --- */ orientation: "horizontal", /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Other --- */ roundedTop: 6 } export default () => { return <BarChart {...frameProps} /> }
Gradient Fill
gradientFill runs a gradient from each bar's tip (opposite the baseline) toward its base. Same API asAreaChart:
true — default fade (80% → 5% of the bar's resolved color).{ topOpacity, bottomOpacity } — explicit opacity stops on the bar's color.{ colorStops: [{ offset, color }, ...] } — arbitrary multi-color gradient.
Default opacity fade:
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: sampleData, /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Customize --- */ gradientFill: true, /* --- Other --- */ roundedTop: 6 } export default () => { return <BarChart {...frameProps} /> }
JSX
<BarChart data={sampleData} categoryAccessor="category" valueAccessor="value" gradientFill roundedTop={6} />
Multi-color gradient via colorStops:
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: sampleData, /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Customize --- */ gradientFill: { colorStops: [{ offset: 0, color: "#f472b6" }, { offset: 0.5, color: "#a855f7" }, ... ] }, /* --- Other --- */ roundedTop: 6 } export default () => { return <BarChart {...frameProps} /> }
JSX
<BarChart data={sampleData} categoryAccessor="category" valueAccessor="value" gradientFill={{ colorStops: [ { offset: 0, color: "#f472b6" }, // pink at the tip { offset: 0.5, color: "#a855f7" }, // purple in the middle { offset: 1, color: "#3b82f6" }, // blue at the base ], }} roundedTop={6} />
Horizontal bars get a left-to-right or right-to-left gradient automatically (direction = tip → base):
import { BarChart } from "semiotic" const frameProps = { /* --- Data --- */ data: sampleData, /* --- Size --- */ margin: { left: 100, top: 20, right: 20, bottom: 30 }, /* --- Layout --- */ orientation: "horizontal", /* --- Process --- */ valueAccessor: "value", categoryAccessor: "category", /* --- Customize --- */ gradientFill: { colorStops: [{ offset: 0, color: "#22d3ee" }, { offset: 1, color: "#2563eb" }] }, /* --- Other --- */ roundedTop: 6 } export default () => { return <BarChart {...frameProps} /> }
Animated Transitions
Set animate to smoothly transition bar heights when data changes. Pass true for defaults (300ms ease-out) or a config object with duration and easing.
JSX
const [data, setData] = useState(datasetA) <BarChart data={data} categoryAccessor="category" valueAccessor="value" animate={{ duration: 500, easing: "ease-out" }} /> <button onClick={() => setData(prev => prev === datasetA ? datasetB : datasetA )}> Swap data </button>
Props
| Prop | Type | Required | Default | Description |
|---|
data | array | Yes | — | Array of data points. Each point should have a category and value. |
categoryAccessor | string | function | — | "category" | Field name or function to access category values. |
valueAccessor | string | function | — | "value" | Field name or function to access numeric values. |
orientation | "vertical" | "horizontal" | — | "vertical" | Chart orientation. Vertical bars grow upward; horizontal bars grow rightward. |
categoryLabel | string | — | — | Label for the category axis. |
valueLabel | string | — | — | Label for the value axis. |
valueFormat | function | — | — | Format function for value axis tick labels. |
colorBy | string | function | — | — | Field name or function to determine bar color. |
colorScheme | string | array | — | "category10" | Color scheme name or custom colors array. |
sort | boolean | string | function | — | false | Sort bars by value. Accepts true, "asc", "desc", or a custom comparator function. |
barPadding | number | — | 5 | Padding between bars in pixels. |
roundedTop | number | — | — | Rounded corner radius on bar tops (the end away from baseline). |
gradientFill | boolean | { topOpacity, bottomOpacity } | { colorStops } | — | false | Gradient running from each bar's tip toward its base. `true` = default 80%→5% opacity fade; object forms mirror AreaChart.gradientFill. Direction follows orientation and sign. |
animate | boolean | object | — | false | Enable animated intro and smooth transitions on data change. `true` for defaults (300ms ease-out), or `{ duration, easing, intro }` for custom. Bars grow from baseline on first render. |
enableHover | boolean | — | true | Enable hover annotations on bars. |
showGrid | boolean | — | false | Show background grid lines. |
showLegend | boolean | — | true (when colorBy set) | Show a legend. Defaults to true when colorBy is specified. |
tooltip | object | function | — | — | Tooltip configuration or render function. |
width | number | — | 600 | Chart width in pixels. |
height | number | — | 400 | Chart height in pixels. |
margin | object | — | { top: 50, bottom: 60, left: 70, right: 40 } | Margin around the chart area. |
title | string | — | — | Chart title displayed at the top. |
frameProps | object | — | — | Additional StreamOrdinalFrame props for advanced customization. Escape hatch to the full Frame API. |
Graduating to the Frame
When you need more control — custom marks, complex annotations, mixed piece types — graduate toStreamOrdinalFrame directly. EveryBarChart is just a configured StreamOrdinalFrameunder the hood.
Chart (simple)
JSX
import { BarChart } from "semiotic" <BarChart data={salesData} categoryAccessor="category" valueAccessor="value" orientation="vertical" sort="desc" categoryLabel="Department" valueLabel="Sales" />
Frame (full control)
JSX
import { StreamOrdinalFrame } from "semiotic" <StreamOrdinalFrame data={salesData} oAccessor="category" rAccessor="value" type="bar" projection="vertical" style={{ fill: "#6366f1" }} oPadding={5} axes={[ { orient: "left", label: "Sales" }, { orient: "bottom", label: "Department" } ]} hoverAnnotation={true} size={[600, 400]} margin={{ top: 50, bottom: 60, left: 70, right: 40 }} />
The frameProps prop on BarChart lets you pass any StreamOrdinalFrame prop without fully graduating:
JSX
// Use frameProps as an escape hatch <BarChart data={salesData} categoryAccessor="category" valueAccessor="value" frameProps={{ annotations: [ { type: "or", category: "Grocery", label: "Top seller" } ], connectorStyle: { stroke: "#999" } }} />
- StackedBarChart — for part-to-whole breakdowns within categories
- DotPlot — a minimal alternative for comparing single values across categories
- StreamOrdinalFrame — the underlying Frame with full control over every rendering detail
- Annotations — adding callouts, highlights, and notes to any visualization
- Tooltips — custom tooltip content and positioning