# LikertStrip (/docs/charts/likert-strip)

LikertStrip answers "does the response lean agree or disagree — and how hard?" — the valence + balance read that
SegmentedBar (unvalenced composition) cannot say. The center line is the question; everything else is the answer.

```tsx
<LikertStrip
  data={[
    { label: "Strongly disagree", value: 10 },
    { label: "Disagree", value: 14 },
    { label: "Neutral", value: 14 },
    { label: "Agree", value: 34 },
    { label: "Strongly agree", value: 28 },
  ]}
  title="Q1 satisfaction"
  width={220}
  height={24}
/>
```

## Install

```tsx
import { LikertStrip } from "@microcharts/react/likert-strip";

<LikertStrip
  data={[
    { label: "Strongly disagree", value: 10 },
    { label: "Disagree", value: 14 },
    { label: "Neutral", value: 14 },
    { label: "Agree", value: 34 },
    { label: "Strongly agree", value: 28 },
  ]}
  title="Q1 satisfaction"
/>
```

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


## When to use it

- **Good for** — survey question rows (share one scale via SparkGroup), sentiment in cards.
- **Avoid for** — more than 7 levels, or exact per-level values (MiniBar).


## Variants

```tsx
// the known critique of center-split neutral — supported, never silent
<LikertStrip data={responses} neutral="omit" />
<LikertStrip data={responses} label="net" />
```

## Edge cases

```tsx
// every level at 0 (or empty data) — nothing to stack, nothing to say
<LikertStrip data={[
  { label: "Disagree", value: 0 },
  { label: "Agree", value: 0 },
]} />
```

```tsx
// every response landed on the neutral level — no lean to report
<LikertStrip data={[
  { label: "Disagree", value: 0 },
  { label: "Neutral", value: 10 },
  { label: "Agree", value: 0 },
]} />
```

Empty data, or data whose values all resolve to 0, has nothing to divide into a diverging read — no bar draws, and the
accessible name says so plainly: **"No responses."** When every non-zero response lands on the neutral level, the bar is
entirely the center segment and the summary reads **"All responses neutral."** instead of forcing a lean out of no
signal. Negative counts are treated as 0 rather than pushed the wrong direction across the center line — a chart that
lies about which side a count is on is worse than one that drops it — and the static entry logs a dev warning when it
happens.


## Why this default

Both neutral conventions are supported honestly: `split` straddles the center (the canonical placement), `omit` removes
neutral from the bar for cleaner pole comparison — but its share is ALWAYS still counted in the total and spoken in the
accessible summary; neutral is never silently dropped. Graded opacity encodes ordinal distance from neutral, never
magnitude.

## Accessibility

The accessible name is the full valence read — **"62% agree, 24% disagree, 14% neutral. Leans positive."** A |net| under
5 points reads "Balanced." The interactive entry steps levels in data order (**"Disagree: 14%, level 2 of 5."**).

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 or press `Escape`.
On touch, a tap pins and a drag scrubs.

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `data` (required) | `{ label; value }[]` | Ordinal levels, negative → positive. |
| `neutral` | `"split" \| "omit"` | Center-straddle or omit-from-bar (always labeled). |
| `label` | `"ends" \| "net" \| "none"` | Agree/disagree % or one signed score. |
| `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).
