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)
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
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
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 or press Escape.
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.