# HistogramStrip (/docs/charts/histogram-strip)

HistogramStrip sorts raw observations into uniform bins and draws the counts zero-anchored, never density-smoothed, so a
distribution's mode, spread, and skew read off one strip. The bin count is √n capped at 12: enough shape to see skew,
few enough bars to survive 60 px. Pre-aggregated counts are not supported; that's SparkBar's contract.

```tsx
<HistogramStrip
  data={Array.from({ length: 120 }, (_, i) => (i % 3 === 0 ? 40 + (i % 10) : 20 + ((i * 7) % 60)))}
  title="Response times"
  style={{ width: 220, height: 56 }}
/>
```

## Install

```tsx
import { HistogramStrip } from "@microcharts/react/histogram-strip";

<HistogramStrip data={times} title="Response times" />
```

Setup (package + stylesheet): [Quickstart](/docs/quickstart#set-up-with-an-ai-agent) or paste [`/agent-setup.md`](/agent-setup.md) into your agent.

## Try it

```tsx
import { HistogramStrip } from "@microcharts/react/histogram-strip/interactive";

<HistogramStrip
  data={times}
  bins={8}
/>
```

## When to use it

Use it for latency clusters in a sentence and distributions per table row. For raw marks use RugStrip; for a series over
time, Sparkline.

## Sizing

**where you fall**

```tsx
const times = Array.from({ length: 120 }, (_, i) =>
  i % 3 === 0 ? 40 + (i % 10) : 20 + ((i * 7) % 60),
);

<HistogramStrip data={times} markValue={45} />
```

**fixed edges across rows**

```tsx
const times = Array.from({ length: 120 }, (_, i) =>
  i % 3 === 0 ? 40 + (i % 10) : 20 + ((i * 7) % 60),
);

<HistogramStrip data={times} domain={[0, 100]} />
```

## Variants

```tsx
const responseTimes = Array.from({ length: 120 }, (_, i) =>
  i % 3 === 0 ? 40 + (i % 10) : 20 + ((i * 7) % 60),
);

<HistogramStrip data={responseTimes} markValue={45} title="You are here" />
```

`markValue` marks the bin its value falls in and never re-bins around it.

```tsx
<HistogramStrip
  data={[12000, 18000, 24000, 30000, 36000, 42000, 18000, 24000, 30000]}
  locale="de-DE"
/>
```

The accessible summary states the modal bin's edges through `format`/`locale` — under `de-DE` a value like 24000 reads
"24.000" (period as the thousands separator) instead of the English "24,000".

## Edge cases

```tsx
<HistogramStrip data={[]} title="No observations yet" />
```

```tsx
<HistogramStrip data={[4, 4, 4, 4, 4]} title="Constant" />
```

An empty series renders zero bars and an accessible name of "No data." rather than a misleading flat line. A constant
series collapses to ONE full-height bin instead of the usual up-to-12 slivers an equal-width binner would draw for a
zero-span domain, and an explicit `bins` count collapses to the observation count when you ask for more bins than you
have values.

## Four homes

**In a sentence**

```tsx
<p>
  API latency this hour{" "}
  <span className="mc-inline">
    <HistogramStrip data={times} width={90} height={18} summary={false} />
  </span>{" "}
  — most calls land 40–50 ms, a few tail past 70.
</p>
```

**In a table cell**

```tsx
<td>
  <HistogramStrip data={Array.from({ length: 20 }, (_, i) => 15 + ((i * 4) % 15))} width={64} height={18} />
</td>
```

**In a KPI card**

```tsx
<div className="kpi">
  <span className="figure">46 ms</span>
  <span className="unit">median</span>
  <HistogramStrip data={times} width={90} height={30} />
</div>
```

**In a tab header**

```tsx
<button className="tab">
  API <HistogramStrip data={times} width={64} height={16} />
</button>
```

## Accessibility

The accessible name names the modal bin: **"120 values, most between 42.09 and 47.36."** The interactive entry roves
bins with range announcements (**"42.09 to 47.36: 26 values."**).

The interactive entry follows the shared [interaction contract](/docs/accessibility#one-interaction-contract):
arrow keys rove between units on both axes, `Home` and `End` jump to the ends, and a click, tap, `Enter` or
`Space` selects a unit — pinning its readout so it survives blur, until you select it again, press `Escape`, or
press outside the chart. On touch, a tap pins and a drag scrubs.

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `data` (required) | `number[]` | Raw observations. |
| `bins` | `number` | Bin count; auto = min(12, √n). |
| `markValue` | `number` | A VALUE whose bin gets accent. |
| `domain` | `[number, number]` | Fixed bin edges across multiples. |
| `format` | `Intl.NumberFormatOptions \| fn` | Formats the bin edges named in the summary. |
| `locale` | `string \| string[]` | BCP 47 locale(s) for the formatted bin edges. |
| `animate` | `boolean` | (interactive) Opt-in entrance motion when the chart mounts client-side — add `import "@microcharts/react/motion"` once. Inert on the server, on hydrated server HTML, and under `prefers-reduced-motion`. |

Plus the shared grammar — `data`, `domain`, `color`, `title`, `summary`, `format` — and the layout props (`width`, `height`, `className`, `style`) that every chart accepts. Interactive entries also share `animate` and `live`, and — wherever a chart has more than one navigable unit — `onActive`, `onSelect`, `selectedIndex` and `defaultSelectedIndex`; and — wherever the chart shows a hover value — `readout`. See [the shared grammar](/docs/quickstart#the-shared-grammar).
