Keyboard Navigation (S2)
Keyboard navigation is an early, work-in-progress feature. It does not yet provide full chart accessibility or screen reader support — treat it as a keyboard-only enhancement, not a complete accessibility solution.
Keyboard navigation currently supports plain, stacked, dodged, and dual-metric-axis Bar charts. Trellis bar configurations and other mark types (Line, Area, Donut, Scatter, etc.) are not yet supported.
Set accessibleNavigation on Chart to let keyboard users navigate bar chart content — individual bars, stacked segments, and their tooltips and popovers — without a mouse.
<Chart data={data} accessibleNavigation>
<Axis position="bottom" baseline title="Browser" />
<Axis position="left" grid title="Downloads" />
<Bar dimension="browser" color="operatingSystem">
<ChartInspect>
{(datum) => (
<div>
<div>Operating system: {datum.operatingSystem}</div>
<div>Downloads: {datum.value}</div>
</div>
)}
</ChartInspect>
<ChartPopover>
{(datum, close) => (
<div>
<div>Operating system: {datum.operatingSystem}</div>
<button onClick={close}>Close</button>
</div>
)}
</ChartPopover>
</Bar>
</Chart>
Keyboard interactions
| Key | Action |
|---|---|
Tab | Focuses the "Enter navigation area" affordance, shown at the top-left of the chart |
Enter | Enters the navigation area, or drills into the focused stack |
Escape | Drills back out one layer; at the top level, exits the navigation area |
Arrow Right / Arrow Down | Moves to the next sibling (bar, stack, or segment) |
Arrow Left / Arrow Up | Moves to the previous sibling |
Space | Opens the ChartPopover for the focused bar, segment, or stack, if one is configured |
Shift+F10 / ContextMenu | The keyboard right-click: on a focused bar or segment, opens its rightClick ChartPopover and calls the Bar's onContextMenu; on a focused legend series, opens the legend's rightClick ChartPopover |
For grouped and dual-metric-axis bars, arrows within a group follow the chart orientation, while the perpendicular arrows move between corresponding bars in adjacent groups. Forward navigation from the last bar in a group enters the first bar in the next group. Navigation does not wrap past the final group.
onContextMenu receives a synthetic contextmenu event positioned at the center of the focused bar, so a menu can be placed next to it. Stacks and categories aren't a single mark, so the keyboard right-click does nothing there.
Bars and segments with a value of exactly 0 are excluded from navigation, since they render invisibly and a mouse could never reach them either.
Focus and hover parity
A keyboard-focused bar drives the same signals real mouse hover drives, so keyboard and mouse interactions look identical: other bars dim the same way, the real ChartInspect tooltip appears with the same content and positioning, and Space opens the real ChartPopover through the same trigger a click uses.
Axis labels on the categorical bottom axis are also keyboard-navigable when they are rendered and not hidden by overlap handling. The axis is its own region below the chart: Arrow Down on the chart root moves to it, and Arrow Up comes back.
Stacked bars
For a stacked Bar (color set), navigation has an extra layer: Enter on the chart root drills into a stack (column), and Enter again drills into an individual segment. Escape reverses this one layer at a time.
Series can span several fields. When color, lineType, and opacity name different fields (for example color="series" and opacity="period" in a time comparison), each bar is identified by all of them, and bars read every field, so bars for different periods are distinct. Dodged-and-stacked bars (a facet set to a two-field array) are navigable too: within a category, the arrows along the orientation move between side-by-side stacks, the perpendicular arrows move through a stack's segments, and moving between stacks lands on the same segment of the next stack.
Number and time dimensions are supported, including 0 and dimensionDataType="time" with date-string data. Bars, stacks, and groups get their focus rings, and bars read the dimension value as written in the data (e.g. "Day: 2024-01-01 00:00:00.0"), not the parsed timestamp. Empty-string dimension values are navigable too; their empty axis tick is skipped, since it has no label to read.
Focusing a stack — before drilling into a segment — shows the dimension-area tooltip or popover, if configured, the same one a mouse hovering the stack's exposed padding would show. See the targets prop on ChartInspect.
Legend
When a bar with a series has a Legend for it, the legend becomes its own navigation region. From the chart root, the arrow pointing toward the legend's position moves to it (Arrow Left for a left legend, Arrow Up for a top one), and the opposite arrow comes back. A bottom legend sits below the bottom axis, so it's reached with Arrow Down from the axis root (or from the chart root when there's no navigable axis).
| Level | Keys |
|---|---|
| Legend | Enter drills into the first series. A focus ring outlines the whole legend. |
| Series | Arrow keys follow the legend's rendered layout, whatever its position. Along the direction its entries are laid out (left/right when they run across rows, up/down when they stack in a column), arrows walk the entries in order and continue onto the next row or column when the legend wraps. The other two arrows only move to the entry directly above/below (or beside) the focused one, and do nothing if there isn't one. Space does what clicking the entry does: opens the legend's ChartPopover, calls onClick, or toggles the series when isToggleable is set. Shift+F10 opens the legend's rightClick ChartPopover. Enter drills into that series' bars. |
| Series bars | Arrows along the chart orientation move between categories in that series. The perpendicular arrows move to the same category in the adjacent series. Escape returns to the series. |
Focusing a series outlines its legend entry and shows its descriptions tooltip. With highlight, it also highlights that series in the chart, the same as hovering the entry. The legend's onMouseOver and onMouseOut fire as focus enters and leaves a series, so a controlled legend (highlightedSeries) follows keyboard focus too.
A legend entry covers every bar that shares its fields. For a legend with keys, or for a series spanning several fields (for example "Add Freeform table | Previous 4 weeks"), Enter on the entry drills into all of its bars. Those bars also read their category, since they're reached outside it.
The legend reads its title and how many series it has, including how many are hidden (e.g. "Operating system legend. 8 series, 1 hidden."). A focused series reads its legend title and the label the legend displays for it (its legendLabels entry, if any), then its descriptions entry (title first, if it has one), then each of its bars, the same way a focused stack itemizes its segments (e.g. "Operating system: Windows. Windows downloads. Browser: Chrome, Downloads: 7. Browser: Firefox, Downloads: 10.").
A series that has been toggled off stays in the legend so you can toggle it back on, but you can't drill into it. It reads as hidden (e.g. "Operating system: Windows. Hidden."). Chart content navigation skips its bars.
Toggling a series re-renders the chart, and focus returns to the same legend entry. That entry's name says what changed, for example "Operating system: Windows. Hidden." or "Operating system: Windows. Shown." followed by its bars, so a screen reader announces the toggle once. If the chart re-renders for any other reason, such as new data, focus returns to the node that had it, which is read again.