# Line Chart

> Lines that show how numbers change over time, with a themed tooltip, legend, and states.

- Name: `line-chart`
- Status: beta
- Categories: charts
- File: the install writes `line-chart.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `recharts`, `react-is`. The install adds them.
- Other registry items: `@arbokui/chart`, `@arbokui/chart-key`. The install adds them.
- Gallery: https://arbokui.com/components/line-chart
- Registry item: https://arbokui.com/r/line-chart.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/line-chart
   ```

## Use it for

- Showing a trend over time or over ordered steps, like daily visits or weekly conversion.
- Comparing the trends of up to five series on one scale.
- Pass data, a config with one entry per line, and the categoryKey for the x axis.
- Pass valueFormat, like { style: "percent" }, to format the tooltip and the y axis.
- Pass legend="top" for a key beside the title in place of the tooltip box. It shows the point under the pointer, and its numbers roll as you move. Press a series in the key to hide or show it.

## Avoid it for

- Categories with no order, like regions. Use BarChart.
- Showing how parts add up to a total over time. Use AreaChart with stacked.
- A small trend next to a number or in a table cell. Use Sparkline.
- More than five lines. The theme has five chart colors.

## Props

- `data`: `TData[]`. One object per point on the x axis, like { day: "Mon", visits: 1250 }.
- `config`: `{ [key in keyof TData]?: { label: string; color?: string } }`. The lines to draw, in order. Colors default to --chart-1 through --chart-5.
- `categoryKey`: `keyof TData`. The field that names each point, shown on the x axis.
- `title`: `ReactNode`. A visible title. It names the chart. TypeScript requires title, aria-label, or aria-labelledby.
- `aria-label`: `string`. Names the chart when it has no visible title.
- `size`: `"sm" | "md" | "lg"`. Default `"md"`. Height: 5, 7, or 9 times --control-h-md, so density scales it.
- `curve`: `"linear" | "monotone" | "step"`. Default `"monotone"`. How lines join their points. Monotone is smooth and never overshoots a point.
- `dots`: `boolean`. Default `false`. Marks every point with a dot. A chart with one point always shows it.
- `valueFormat`: `Intl.NumberFormatOptions`. Formats tooltip values, and y axis ticks in short form, like 12.5K.
- `locale`: `string`. Default `"en-US"`. The locale for numbers. Fixed, so server and browser print the same text.
- `legend`: `boolean | "top"`. Shows the legend. By default it shows when there are two or more lines. "top" shows it as a key beside the title, with the point under the pointer in place of the tooltip box, and the last point at rest.
- `loading`: `boolean`. Default `false`. Shows a soft line shape at the same height. When data arrives, it fades out while the lines draw in.
- `error`: `ReactNode`. Shows this message in place of the chart. true shows a default message.
- `onRetry`: `() => void`. Shows a retry button under the error.
- `emptyText`: `ReactNode`. Default `"No data yet"`. Shown when data is empty.
- `className`: `string`. Extra classes. Later classes win, so className='h-96' replaces the height.

## Accessibility

- Renders a \<figure> named by its title, or by aria-label. TypeScript requires one.
- Recharts' keyboard layer stays on: Tab focuses the chart, the arrow keys move between points, and the tooltip reads each one out. With the key on top, the key follows the arrow keys too, and the tooltip stays on the page for screen readers only, so each point is still read out.
- The key on top sits beside the 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 series in the key is a toggle button. A hidden line fades out where it is, leaves the tooltip, and keeps the y axis still. The last one shown cannot hide. Tab reaches these buttons first, then the chart.
- Keeps one height while it loads, draws, fails, or has no data, so the page does not move. When the page prints, it asks the browser to keep a chart that fits on one page whole. In the light theme, it asks the browser to print legend dots and loading shapes even with backgrounds off.
- Loading, the error, and the empty text are read out through a status line that stays on the page.
- Line colors come from --chart-1 to --chart-5, which the theme tests hold to 3:1 against the page. The legend and tooltip name each line in text.
- Lines draw in over three times --motion-duration-base, once the chart is on screen. They finish at once when the page prints. At 0ms they draw at once, and Recharts skips the animation for reduced motion.

## Examples

### Two lines

```tsx
const data = [
  { day: "Mon", desktop: 1250, mobile: 860 },
  { day: "Tue", desktop: 1410, mobile: 920 },
  { day: "Wed", desktop: 1180, mobile: 1040 },
];

<LineChart
  title="Visits by device"
  data={data}
  config={{ desktop: { label: "Desktop" }, mobile: { label: "Mobile" } }}
  categoryKey="day"
/>
```

### Key beside the title in place of the tooltip

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

### Percent, with a dot on every point

```tsx
<LineChart
  title="Conversion rate"
  data={[
    { week: "W1", rate: 0.021 },
    { week: "W2", rate: 0.026 },
    { week: "W3", rate: 0.031 },
  ]}
  config={{ rate: { label: "Conversion" } }}
  categoryKey="week"
  dots
  valueFormat={{ style: "percent", minimumFractionDigits: 1 }}
/>
```

### While it loads, and when it fails

```tsx
<LineChart
  aria-label="Visits by device"
  data={data ?? []}
  config={{ desktop: { label: "Desktop" }, mobile: { label: "Mobile" } }}
  categoryKey="day"
  loading={isLoading}
  error={error ? "Visits could not load." : undefined}
  onRetry={() => refetch()}
/>
```
