LikertStrip
LikertStrip stacks ordinal survey responses either side of a center line and reads which way they lean.
- encodes
- signed segment length from a center line
- precision
- medium — MiniBar for exact per-level values
- nodes
- ≤ 10 (≤ 7 segments + hairline + 2 labels)
LikertStrip stacks ordinal responses on either side of a center line: disagree to the left, agree to the right. Graded
opacity encodes ordinal distance from neutral, never magnitude. Where SegmentedBar shows composition without valence,
this reads the lean and how hard it leans. Both neutral conventions ship. neutral="split" straddles the center line,
the canonical placement; neutral="omit" takes neutral out of the bar for a cleaner pole comparison, and its share is
still counted in the total and spoken in the accessible summary.
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
Use it for survey question rows (share one scale via SparkGroup) and sentiment in cards. Avoid it past 7 levels; for exact per-level values use 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 across the center line onto the wrong side, and the static entry logs a dev warning when it happens.
Four homes
Accessibility
The accessible name carries the full valence read: "62% agree, 24% disagree, 14% neutral. Leans positive." A |net| under 5 points reads "Balanced." The interactive entry steps the levels in data order and announces the response count beside the share it was computed from: "Disagree: 14% (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.