Skip to main content

Bar (S2)

Alpha

The Bar component in the S2 package supports nearly all props from the base Bar component plus S2-exclusive features: inline direct labels and Spectrum 2 styled visuals.

note

The S2 Bar component does not yet support Trendline as a child component.

See Keyboard Navigation for the accessibleNavigation chart prop, currently supported only for Bar.

import { Chart, Axis, Bar } from '@spectrum-charts/react-spectrum-charts-s2';

Bar direct labels (BarDirectLabel)​

The BarDirectLabel component is an S2-exclusive child of Bar. It places a numeric label on each bar, reading directly from the metric value. By default, labels sit outside the bar tip — above or below the bar for vertical charts, left or right for horizontal charts — and flip to the opposite side for negative values. Labels follow each bar in dodged and stacked layouts.

Labels never overlap other labels or bars. Outside labels that would collide are hidden, and inside labels that do not fit within their bar are hidden (or moved outside with overflow="spill"). Hidden values remain available through tooltips.

<Chart data={data}>
<Axis position="bottom" baseline title="Browser" />
<Axis position="left" grid title="Downloads" />
<Bar dimension="browser" metric="downloads">
<BarDirectLabel />
</Bar>
</Chart>

Bar direct label light Bar direct label dark

Horizontal bars​

The same component works for horizontal bar charts. Labels appear to the right of positive bars and to the left of negative bars.

<Chart data={data}>
<Axis position="left" baseline title="Browser" />
<Axis position="bottom" grid title="Downloads" />
<Bar dimension="browser" metric="downloads" orientation="horizontal">
<BarDirectLabel />
</Bar>
</Chart>

Bar direct label horizontal light Bar direct label horizontal dark

Labeling specific bars​

Set dataKey to a boolean field in your data to label only the rows where that field is truthy. These labels follow the same fit and collision rules as other labels.

const data = [
{ channel: 'Email', subscribers: 12600, callout: false },
{ channel: 'Social', subscribers: 6200, callout: true },
];

<Bar dimension="channel" metric="subscribers">
<BarDirectLabel dataKey="callout" />
</Bar>;

BarDirectLabel props​

The label text is derived automatically from the parent Bar's metric, dimension, and orientation.

nametypedefaultdescription
position'start' | 'middle' | 'end' | 'end-outside''end-outside'Where to place the label relative to the bar. 'end-outside' places it outside the bar tip; 'end' places it inside the bar, 8px from the tip; 'middle' centers it within the bar; 'start' places it inside the bar, 8px from the baseline edge.
format'currency' | 'shortCurrency' | 'shortNumber' | 'standardNumber' | 'percentage' | string',.2~f'Number format for the label value. Accepts a named preset or a custom d3-format specifier string (e.g. '.1f').
overflow'hide' | 'spill''spill' for 'start', otherwise 'hide'What happens to an inside label ('start', 'middle', 'end') that does not fit in its bar. 'hide' hides it; 'spill' moves it outside the bar tip, where it is hidden if it would collide with another label or bar.
dataKeystring–Boolean data field. Only rows where it is truthy are labeled.

Diverging bars​

Set diverging on Bar for a metric that spans positive and negative values (e.g. percent change). It moves the categorical axis to the zero baseline and flips each axis label to the side opposite its bar, so labels never overlap the bars.

<Chart data={data}>
<Axis position="left" baseline />
<Axis position="bottom" grid labelFormat="percentage" />
<Bar dimension="channel" metric="changeRate" orientation="horizontal" diverging>
<BarDirectLabel position="start" format="percentage" />
</Bar>
</Chart>
Single-series only

diverging only supports a single-series bar (no color, lineType, or opacity facet, and not type="dodged") that is the only bar mark on the chart. It is also a no-op on a trellised chart or when the axis has subLabels. In any of these cases the axis stays at its normal position and diverging has no effect.


Draw-in animation​

Add 'drawIn' to the chart's animationTypes to grow the bars from the baseline over 700ms with the Spectrum 2 ease-in-out curve. Stacked segments fill in order from the baseline outward. Direct labels and annotations start a 150ms linear fade as soon as their own bar or segment finishes drawing.

<Chart data={data} animationTypes={['hover', 'drawIn']}>
<Bar dimension="browser" metric="downloads" />
</Chart>

Draw-in is off by default. animations={false} disables it even when 'drawIn' is listed. When a chart draws in more than one mark type, every mark uses the longest duration so they finish together. When the user prefers reduced motion, draw-in is skipped and hover fades still run.


Bar props (S2)​

nametypedefaultdescription
childrenChartInspect | ChartPopover | BarAnnotation | BarDirectLabel–Optional child components for tooltips, popovers, annotations, and inline direct labels.
colorstring | {value: string}'categorical-100'Key in the data used to map each series to a color, or a fixed color value object.
dimensionstring'category'Key in the data used for the categorical axis.
divergingboolean–Moves the categorical axis to the zero baseline and flips each label to the opposite side of its bar. Single-series bars only — see the note above.
metricstring'value'Key in the data used for the metric axis value.
namestring'bar0'Name of the bar component. Useful when referencing a specific bar programmatically.
onClick(datum: Datum) => void–Callback fired when a bar is clicked.
orientation'vertical' | 'horizontal''vertical'Controls whether bars extend vertically (default) or horizontally.
type'stacked' | 'dodged''stacked'Controls whether multi-series bars are stacked on top of each other or placed side by side.