Skip to content
txbrendan/ui

Chart Key

beta

A key for a chart's title row that shows the point under the pointer, with numbers that roll as it moves. Area Chart, Bar Chart, and Line Chart use it for legend="top".

Preview

Visitors by device
  • Jun

Visits by device
  • Fri

Install

  1. 1. Add the registry to components.json, once per app. Without it, the shadcn CLI looks up @txbrendan in a public list that txbrendan/ui does not control.

    npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"
  2. 2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.

    npx shadcn@latest add @txbrendan/theme
  3. 3. Add the component.

    npx shadcn@latest add @txbrendan/chart-key

Use it for

  • A chart that shows its values in the title row in place of a tooltip box. Pass legend="top" to Area Chart, Bar Chart, or Line Chart, which use this for you.
  • A chart of your own on the chart base. Call useChartKey, pass its key as the Chart's legendContent, set legendPosition to "top", and put ChartKeyTracker inside the Recharts chart.
  • Each series in the key is a button that hides or shows it. Give each series' layer keySeriesClass(hidden.has(key)) so it fades, and tooltipType="none" while hidden. In a stack, pass the data through withoutHidden(data, gone), so the rest close the gap once it has faded.

Avoid it for

  • A chart people read point by point with many series. Past three series the key wraps, and a tooltip by the pointer is easier to read.
  • Charts with no order on the x axis, like a donut. The key follows the point under the pointer along the x axis.

Props

  • useChartKey

    Hook. Builds the key for the Chart's legendContent, and the point to pass to ChartKeyTracker. At rest it shows the last point. hidden holds the series turned off in the key. gone holds those whose fade has ended.

    (options: { data; categoryKey; series; valueFormat?; locale? }) => { key; point; hidden; gone }

  • ChartKeyTracker

    Put it inside the Recharts chart. It tells the key which point is under the pointer or the keyboard. It draws nothing.

    ({ point }) => null

  • keySeriesClass

    Classes for a series' layer, so a hidden one fades out where it is over --motion-duration-base.

    (hidden: boolean) => string

  • withoutHidden

    The data with each series in gone at zero, for a stacked chart. Recharts glides the stack to its new shape.

    (data, gone) => data

Accessibility

  • The key sits beside the chart's title, not in it, so the chart's name never changes as the key moves.
  • Each value holds the width of its longest one, so the key stays still as its numbers roll. Each number keeps its full text for screen readers.
  • Keep the chart's tooltip on the page with the sr-only class, so the keyboard layer still reads each point out.
  • Each series is a toggle button with aria-pressed. Hidden, its swatch empties to an outline and its value dims, and nothing changes size. The last series shown is aria-disabled, so the plot never goes blank.
  • One highlight glides between the buttons as the pointer moves, and a press darkens it. Each button shows the focus ring from the keyboard.
  • The digits roll on the motion variables. With motion off or reduced, they change at once.
  • While the chart loads, each value holds a placeholder and the buttons are aria-disabled. When the values land, the buttons glide to their new places. With motion off or reduced, they move at once.

Examples

Key beside the title, on a line chart

<LineChart
  title="Visits by device"
  data={[
    { day: "Mon", desktop: 1250, mobile: 860 },
    { day: "Tue", desktop: 1410, mobile: 920 },
  ]}
  config={{ desktop: { label: "Desktop" }, mobile: { label: "Mobile" } }}
  categoryKey="day"
  legend="top"
/>