# ASCII Line Chart

> ASCII line charts with axes, several series and a scrubbing readout.

Category: Charts. Docs: https://asciicn.sumak.dev/docs/ascii-line-chart

## Installation

```bash
npx shadcn@latest add @asciicn/ascii-line-chart
```

Needs the `@asciicn` registry in components.json: `"registries": { "@asciicn": "https://asciicn.sumak.dev/r/{name}.json" }`.

## Usage

```tsx
import { AsciiLineChart } from "@/components/ascii/ascii-line-chart"

<AsciiLineChart
  label="Visitors today"
  series={[
    { label: "today", data: [220, 310, 540, 980, 1240, 860] },
    { label: "yesterday", data: [200, 280, 450, 760, 990, 720], className: "text-muted-foreground" },
  ]}
  labels={["09:00", "11:00", "13:00", "15:00", "17:00", "19:00"]}
/>
```

## Examples

### Units and a fixed scale

Pin `min={0}` so a small change does not look like a cliff, and pass `format` to put units on the axis and in the readout.

```tsx
<AsciiLineChart
  label="API latency"
  series={[
    { label: "p50", data: p50 },
    { label: "p95", data: p95, className: "text-amber-500" },
  ]}
  labels={hours}
  min={0}
  width={40}
  height={8}
  format={(v) => `${v}ms`}
/>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `series` | `{ label, data, className? }[]` |  | One line per entry. `className` colours it; otherwise primary, amber, sky and destructive in turn. |
| `label` | `string` |  | Names the chart for screen readers and captions its data table. |
| `labels` | `string[]` |  | One per data point. A few are shown along the x axis, and the current one in the readout. |
| `width` | `number` | `60` | Plot width in characters. Narrows to fit a smaller container. |
| `height` | `number` | `12` | Plot height in rows, one value level each. |
| `min / max` | `number` | `data range` | Fix the y scale. Values outside it are clamped to the edge. |
| `stacked` | `boolean` | `false` | Pile each series on the ones before it. The readout still shows each series' own value. |
| `format` | `(v) => string` | `String` | Formats axis ticks, the readout and the data table. |
| `animate` | `boolean` | `true` | Draw the lines in from the left the first time the chart scrolls into view. |

## Notes

- **Accessibility.** A focusable group named by `label`. Arrow keys move the cursor, Home and End jump to the ends, Escape clears it, and a live region reads out the values. A visually hidden table holds every data point.
- **Drawing.** Lines are plain ASCII: `_` along a row, `/` or `\` to step one row and `|` for bigger jumps. Values between samples are interpolated, one per column. Every cell belongs to one series, and the first series wins where lines meet, so it always reads unbroken.
- **Theming.** Each series is its own text layer, so any `text-*` class colours it. Hovering a series in the readout fades the others.
- **Motion.** The plot is revealed left to right with a clip. The cursor glides between points. Everything holds still under `prefers-reduced-motion`.
- **Sizing.** The chart fills its container's width and draws up to `width` characters of plot, fewer when the container is narrower. Give it a width in inline or table layouts.
- **Fonts.** Rows are exactly 1em tall and clipped, so `_` sits on the row below and strokes join up in any monospace font. The cursor and x labels are placed by percentage, so they stay aligned even if a fallback draws the axes at another width.
- **Dependencies.** `motion` for the entrance and transitions.
