RugStrip
RugStrip marks every raw observation as a tick on one line, with stacked duplicates darkening into density.
- encodes
- tick position; density via ink accumulation
- precision
- high per observation, medium for density
- nodes
- ≤ 4 (opacity-tiered tick paths + markValue)
- collection
- Core
RugStrip puts every value in a sample on one line as its own tick, so the full spread and the places the values crowd
read straight off the marks. Every tick is one real observation: no binning, no jitter, no thinning. Coincident values
darken through three opacity tiers (35%, 60%, 85%), so a lone tick stays visible while a stack reads as density; the
tiers are bucketed because a browser paints one path's stroke as a single operation, so the overlap compositing you
might expect never happens. markValue adds a full-height highlighted tick for one raw value against the field, which
is the strongest single read the strip offers; the regular ticks are inset by one unit so that highlight reads taller
without escaping the box.
Install
import { RugStrip } from "@microcharts/react/rug-strip";// salaries, yourOffer — real values under “Sample data” below<RugStrip data={salaries} markValue={yourOffer} title="Pay band" />Sample data
const salaries = [42, 48, 51, 53, 55, 58, 61, 63, 66, 71, 55, 52, 49, 58, 62, 75, 83, 58, 54, 60];const yourOffer = 62;Try it
- hover · rove · click…
Hover for the nearest observation; arrow keys walk them in sorted order with rank readouts.
import { RugStrip } from "@microcharts/react/rug-strip/interactive";// salaries, yourOffer — real values under “Sample data” below<RugStrip data={salaries} markValue={yourOffer}/>Sample data
const salaries = [42, 48, 51, 53, 55, 58, 61, 63, 66, 71, 55, 52, 49, 58, 62, 75, 83, 58, 54, 60];const yourOffer = 62;When to use it
Use it for a "you are here" read in a pay band, raw spread beside a stat, or margin composition under a Sparkline. Past about 400 observations, reach for HistogramStrip: a rug promises raw marks and never downsamples. For trends over time use Sparkline.
Sizing
Variants
Edge cases
Empty data draws a centered axis line rather than a blank hole, so the strip still reads as a rug with nothing on it instead of a layout gap.
A single value (or an all-equal field) has a zero-span domain; the tick renders at the strip's midpoint instead of dividing by zero.
A markValue outside the observed domain clamps to the nearest edge. It never escapes the box, and it never rescales
the field around itself.
Four homes
Their $62k offer sits inside the band, not at either edge.
| Engineering | $62k | |
| Design | $46k | |
| Sales | $40k |
Preview uses the public chart API only. When an interactive twin exists, it swaps in with the same props and no entrance motion - code samples stay on the static import. Placement recipes: Composition, Sizing.
Accessibility
The accessible name is the distribution: "8 values from 42 to 75, median 59.5." The interactive entry walks the observations in sorted order and announces each one with its rank: "48 — 2nd of 17."
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, press Escape, or
press outside the chart. On touch, a tap pins and a drag scrubs.
Props
| Prop | Type | Notes |
|---|---|---|
| data* | number[] | Raw observations — position = value. |
| markValue | number | One value emphasized against the field. |
| orientation | "horizontal" | "vertical" | Vertical rugs sit beside distributions. |
| domain | [number, number] | Fix the scale across rows (rugs mislead worst under per-row autoscale). |
| 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.