Hourglass
React hourglass chart — sand area that splits elapsed and remaining, area-true. Tiny accessible SVG microchart; RSC-safe static or /interactive.
- encodes
- sand area split top (remaining) / bottom (elapsed)
- precision
- medium
- nodes
- 4
Hourglass answers "how much time is gone and how much remains?" — the two-sided story a progress bar can't tell. Sand fills the top chamber (remaining) and the bottom (elapsed), and both areas are area-true: a naive linear-height fill in a triangular bulb would overstate early progress by up to 2×, so the geometry solves for true proportional area. A thin stream at the neck marks "running"; it disappears at both ends, because finished and not-started are shape-distinct states.
Install
import { Hourglass } from "@microcharts/react/hourglass";<Hourglass value={0.75} title="Session" />Try it
When to use it
- Good for — a deadline or session-expiry read in a sentence, a TTL cell where remaining is the story, or a time-boxed tab or countdown.
- Avoid for — exact percentages (Progress), trends (Sparkline), or non-time fractions.
Sizing
Variants
Edge cases
Four homes
Why this default
value is the elapsed fraction — the same polarity as Progress — so the two compose in one product without
re-learning which way is which. The area-true solve is the load-bearing honesty rule: in an inherently nonlinear
container, the sand areas are exactly proportional to elapsed and remaining. The stream is a binary state mark, not
decoration, and is never animated in the static entry — it simply renders while 0 < value < 1.
Accessibility
The accessible name carries both sides — a glyph above reads "70% elapsed, 30% remaining." The interactive entry cross-fades the sand levels on change (opacity plus a scale-from-the-floor settle, never a path interpolation) and announces only when the value crosses a documented threshold (50 / 90 / 100%), so a streaming value never spams.
This chart is a single unit, so there is nothing to rove between: a click, tap, Enter or Space selects it
and fires onSelect, and no selection stays pinned. That is the scalar half of the shared
interaction contract.
Hover or focus also reveals the reading itself in a floating chip, for the sizes and label modes where the mark
does not print it; readout={false} drops the chip and keeps everything else.
Props
| Prop | Type | Notes |
|---|---|---|
| value* | number | Elapsed fraction 0–1 (like Progress). |
| stream | boolean | The running-sand cue (default true). |
| label | "none" | "remaining" | "elapsed" | Print the percent that matters to the context. |
| fontSize | number | Type size of the percent numeral, in viewBox units (default 8). |
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.
Related charts
MoonPhase
React moon phase chart — lunar phase as an honest illuminated disk — fraction lit, not decoration. Tiny accessible SVG microchart; RSC-safe static or /interactive.
BalanceBeam
React balance beam chart — which of two sides outweighs, with area-true weights. Tiny accessible SVG microchart; RSC-safe static or /interactive.