Recharts Accessibility

Permalink to "Recharts Accessibility"

Recharts is a popular React charting library that renders SVG through declarative components. Its accessibility support is basic but improving: an accessibilityLayer prop on chart containers adds keyboard navigation of data points via the tooltip, with arrow keys moving between points and the tooltip content announced. It does not write descriptions, provide data tables or choose colour-independent styles; those are yours to add around and inside the chart.

This guide belongs to chart library accessibility.

Spec reference

Permalink to "Spec reference"
  • accessibilityLayer — on LineChart, BarChart and others in recent versions; makes the chart focusable and lets arrow keys move the active tooltip; tooltip content is exposed via a live region.
  • SVG accessibility — the chart svg can take role="img" with aria-label, or be wrapped in a figure with a caption.
  • SC 1.1.1 (A) — text alternative; SC 2.1.1 (A) — keyboard; SC 1.4.1 (A) — colour independence.
Recharts defaults versus an accessible setup Comparison: defaults render an unlabelled SVG with hover tooltips and colour-only series; an accessible setup adds a figure with caption, accessibilityLayer, dashed or shaped series and a table. Recharts defaults versus an accessible setup✗ DefaultsUnlabelled SVGHover-only tooltipsSeries by colourNo data accessLegend as text only✓ Accessible setupFigure with heading and captionaccessibilityLayer: arrow keys andannouncementsstrokeDasharray, dot shapes, direct labelsData table toggleLegend explains patterns

When to use — and when not to

Permalink to "When to use — and when not to"

Recharts suits React dashboards with standard chart types. Turn on accessibilityLayer, wrap every chart in a figure with a heading and summary, and provide a table.

For complex accessibility requirements (sonification, detailed point descriptions, keyboard navigation across many series), consider a library with a deeper accessibility module, or supplement Recharts with your own navigation.

The misapplication: relying on the tooltip as the only place values appear, with tooltips that show only on hover.

Making a Recharts chart accessible Flow: wrap in a figure with heading and caption; enable accessibilityLayer; style series with patterns and labels; add a data table toggle; check custom tooltip content. Making a Recharts chart accessibleFigureheading and summary captiontext alternativeaccessibilityLayerkeyboard and announced tooltipinteractionSeries stylesdashes, shapes, labelscolour independenceData tabletoggle beside the chartcomplete dataTooltip contentunits and namesreadable announcements

Annotated code example

Permalink to "Annotated code example"
import { LineChart, Line, XAxis, YAxis, Tooltip, Legend, ResponsiveContainer, LabelList } from 'recharts';

function RevenueChart({ data }) {
  const [showTable, setShowTable] = useState(false);
  return (
    <figure aria-labelledby="rev-h" aria-describedby="rev-sum">
      <h3 id="rev-h">Revenue by region, 2026</h3>
      <p id="rev-sum">North grew fastest (+18%); South declined in Q3.</p>
      <ResponsiveContainer width="100%" height={320}>
        <LineChart data={data} accessibilityLayer>                         {/* keyboard + announced tooltip */}
          <XAxis dataKey="quarter" label={{ value: 'Quarter', position: 'insideBottom', offset: -4 }} />
          <YAxis label={{ value: 'Revenue (million euros)', angle: -90, position: 'insideLeft' }} />
          <Tooltip formatter={(v) => `${v} million euros`} />               {/* units in announcements */}
          <Line dataKey="north" name="North" stroke="#155c38" dot={{ r: 4 }}>
            <LabelList dataKey="north" position="top" />                   {/* direct labels */}
          </Line>
          <Line dataKey="south" name="South" stroke="#8a6000" strokeDasharray="6 4" dot={{ r: 4, strokeWidth: 2 }} />  {/* dashed: not colour only */}
          <Legend />
        </LineChart>
      </ResponsiveContainer>
      <button type="button" aria-expanded={showTable} onClick={() => setShowTable(s => !s)}>
        {showTable ? 'Hide' : 'Show'} revenue data table
      </button>
      {showTable && <RevenueTable data={data} />}
    </figure>

  );
}

Keyboard & AT behaviour

Permalink to "Keyboard & AT behaviour"
Interaction Behaviour with accessibilityLayer Expected announcement
Tab Focus the chart Chart (figure name from context)
Right / Left Move active point Tooltip content: “Q3, North: 4.6 million euros, South: 2.9 million euros”
Tab Leave the chart Next control (table toggle)
Enter on table toggle Show table “Show revenue data table, expanded”
Recharts accessibility features Matrix of concerns — keyboard access, tooltip announcements, chart name and description, colour independence, data table, legend toggles — against provided or your job. Recharts accessibility featuresProvidedYour jobKeyboard accessaccessibilityLayerNoTooltip announcementsWith accessibilityLayerUnits in formatterName and descriptionNoFigure, heading, captionColour independenceNoDashes, shapes, labelsData tableNoTable toggleLegend togglesNoBuild as buttons if needed
Recharts provides keyboard tooltip access; the rest is yours.

Integration context

Permalink to "Integration context"

Table toggles follow show-as-table toggles for charts. Direct labelling is covered in direct labelling instead of legends, and keyboard models in adding keyboard navigation to SVG line charts.

Gotchas

Permalink to "Gotchas"

Version. accessibilityLayer arrived in Recharts 2.x minor releases and its behaviour evolved; check your version and enable it explicitly where it is not the default.

Multiple charts. Several charts each with keyboard focus add tab stops; that is acceptable, but give each figure a heading so users know which chart they are in.

Custom tooltips. If you render a custom tooltip component, make sure its text includes series names and units — it is what gets announced.

Worked example

Permalink to "Worked example"

A React product analytics dashboard used eight Recharts charts with colour-only lines and hover tooltips. After enabling accessibilityLayer, adding figure headings and summaries, dashed and dotted line styles, direct end labels, tooltip formatters with units and a “Show data table” toggle per chart, a screen reader user could explore each chart by arrow keys and read the full data in tables. The design team liked the direct labels enough to remove most legends.

A ChartFigure wrapper

Permalink to "A ChartFigure wrapper"
function ChartFigure({ title, summary, table, children }) {
  const id = useId(); const [open, setOpen] = useState(false);
  return (
    <figure aria-labelledby={`${id}-t`} aria-describedby={`${id}-s`}>
      <h3 id={`${id}-t`}>{title}</h3>
      <p id={`${id}-s`}>{summary}</p>
      {children}                                         {/* the Recharts chart with accessibilityLayer */}
      <button type="button" aria-expanded={open} onClick={() => setOpen(o => !o)}>{open ? 'Hide' : 'Show'} data table</button>
      {open && table}
    </figure>

  );
}

Every Recharts chart in the product goes through this wrapper, so titles, summaries and tables are never forgotten.

Testing it with a screen reader

Permalink to "Testing it with a screen reader"
  1. Navigate to each figure by heading; confirm the summary.
  2. Tab into the chart; use arrows; confirm tooltip announcements with units and series names.
  3. View the chart in greyscale; confirm series remain distinguishable.
  4. Open the table; confirm it matches the chart data.

Common mistakes

Permalink to "Common mistakes"
  • accessibilityLayer not enabled.
  • Unitless tooltip values.
  • Colour-only lines.
  • No data table.

Adoption checklist for teams

Permalink to "Adoption checklist for teams"
  1. Wrap Recharts charts in a ChartFigure component with required title and summary.
  2. Enable accessibilityLayer in a shared chart defaults helper.
  3. Provide series style presets with dashes and markers.
  4. Include a table toggle in ChartFigure.
  5. Test each chart type with a screen reader once, then reuse.

FAQ

Permalink to "FAQ"
Does Recharts support keyboard navigation?

With accessibilityLayer in recent versions, yes, through tooltip navigation.

Does it add aria-labels to the SVG?

Not meaningful ones by default; name the chart through a surrounding figure and heading.

How do I make bars distinguishable without colour?

Use patterns (SVG pattern fills), direct value labels and clear series names.

Can legends toggle series accessibly?

Recharts legends are not buttons by default; build an HTML toggle group if you need series toggling.

Is Recharts suitable for complex accessibility needs?

For standard dashboards, yes with additions. For extensive keyboard exploration or sonification, consider libraries with deeper support.

How do I handle responsive charts?

ResponsiveContainer resizes the SVG; ensure text remains readable at small sizes and the table remains available.

What about dark mode?

Pass theme-aware colours and verify contrast in both themes.

How do I add patterns to bars in Recharts?

Define SVG pattern elements in a defs block inside the chart and reference them with fill=“url(#pattern-id)” on Bar components; keep a solid outline for contrast.

Does accessibilityLayer work with all chart types?

It is available on the common cartesian charts in recent versions; check pie and radial charts in your version, and fall back to a table and summary where it is missing.

Can I customise what accessibilityLayer announces?

The announcement comes from tooltip content, so a custom Tooltip component or formatter controls it. Include series names and units.

How do I handle charts with many series?

Limit visible series, offer legend toggles as HTML buttons, and keep the table as the complete view.

Permalink to "Related"

← Back to Chart Library Accessibility