LikertStrip
React likert strip chart — ordinal survey responses on a shared strip. Tiny accessible SVG microchart; RSC-safe static or /interactive.
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.
Install
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"/>Try it
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).
Sizing
Variants
Edge cases
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.
Four homes
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:
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 | Notes |
|---|---|---|
| data* | { 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 | interactiveOpt-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.