TanStack
Catalog

Industry unemployment with end labels

trend

101 lines · 2 files · 2.7 kB

cases/02-multi-line-end-labels/example.tsx78 lines · entry
cases/02-multi-line-end-labels/example.tsx
import { Chart } from '@tanstack/charts/react/tooltip'
import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip'

import { defineChart, lineY, select, text } from '@tanstack/charts'
import { scaleLinear, scaleUtc } from 'd3-scale'
import { industries } from '@tanstack/charts-data/industries'
import { selectMultiLineData } from './selection'
import type { MultiLineDatum } from './selection'

const colors = ['#2563eb', '#ea580c', '#059669']

export const createExampleChart = (input: ChartOptions) => {
  const rows: readonly MultiLineDatum[] = selectMultiLineData(
    industries,
    input.revision,
  )
  const preview = input.preview === true
  const endpoints = select(rows, {
    by: 'industry',
    value: (datum) => datum.date.getTime(),
    select: 'max',
  })

  return defineChart(
    {
      marks: [
        lineY(rows, {
          id: 'industry-lines',
          x: 'date',
          y: 'unemployed',
          color: 'industry',
          strokeWidth: 2.25,
        }),
        text(endpoints, {
          id: 'industry-end-labels',
          x: 'date',
          y: 'unemployed',
          text: 'industry',
          color: 'industry',
          anchor: preview ? 'end' : 'start',
          dx: preview ? -5 : 5,
          fontWeight: 600,
        }),
      ],
      scales: {
        x: { scale: scaleUtc, axis: { label: 'Week' } },
        y: {
          scale: scaleLinear,
          grid: true,
          axis: { label: 'Unemployed (thousands)' },
        },
      },

      color: {
        range: colors,
      },
      margin: { right: 112 },
    },
    { keyboard: true, tooltip: exampleTooltip },
  )
}

export interface ChartOptions {
  revision: number
  preview?: boolean
}

export const exampleAriaLabel =
  'Unemployment by industry with direct end labels'

export const chart = createExampleChart({
  revision: 0,
  preview: false,
})

export default function Example() {
  return <Chart ariaLabel={exampleAriaLabel} definition={chart} height={480} />
}
cases/02-multi-line-end-labels/selection.ts23 lines · dependency
cases/02-multi-line-end-labels/selection.ts
import type { IndustriesRow } from '@tanstack/charts-data/industries'

export const industryNames = ['Manufacturing', 'Construction', 'Finance']
export type IndustryName = (typeof industryNames)[number]
export type MultiLineDatum = IndustriesRow & {
  readonly industry: IndustryName
}

export function selectMultiLineData(
  rows: readonly IndustriesRow[],
  revision = 0,
): readonly MultiLineDatum[] {
  const offset = Math.abs(revision) % 2
  const start = Date.UTC(2000, offset)
  const end = Date.UTC(2003, offset)

  return rows.filter(
    (row): row is MultiLineDatum =>
      row.date.getTime() >= start &&
      row.date.getTime() < end &&
      industryNames.some((industry) => industry === row.industry),
  )
}