Lane Meter
Compare workloads across queues or pipeline stages on a shared grid.
import { Lane, LaneItem, LaneMeter } from '@youj/react'
Installation & usage
npm i @youj/reactFor an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.
Use a lane meter where a workload moves through states and people compare them at a glance: queued, running, failed and done jobs; builds by stage; requests by region. Every lane has as many cells as the others, so the rows form one ruled grid. A lane with its own capacity (worker slots, a queue's size) fills against it and shows it muted beside the value ("24 / 32"); the other lanes share one scale. For one resource on its own, use a Segmented Meter; for a share of a whole in a table row, use a Share Bar.
import { Button, LaneMeter } from '@youj/react'
<LaneMeter
lanes={[
{ id: 'queued', label: 'Queued', value: 214, max: 500 },
{ id: 'running', label: 'Running', value: 24, max: 32, tone: 'accent', active: true },
{ id: 'failed', label: 'Failed', value: failed.length, tone: 'danger', items: failed, action: <Button size="xs" variant="secondary">Retry all</Button> },
{ id: 'done', label: 'Done', value: 12480, max: 16000, tone: 'success' },
]}
format={{ notation: 'compact', maximumFractionDigits: 1 }}
onItemAction={(item) => retry(item)}
/>Each lane takes a label, a value and, optionally, its own max, a tone (a status, the accent, a chart color or neutral, the ink), active for work in progress and an action for its end. segments sets the cells per lane (default 32) and format takes Intl.NumberFormat options for the values.
Description
Queued, running and failed job lanes, where the failed lane lists its jobs and can retry them.
A lane with items lights one cell per item, such as a failed job. With onItemAction, each item is a button with a tooltip (its label and detail), named by the action and the item ("Retry job-8f2a1c"; set the verb with itemActionLabel). The lane is one tab stop: arrow keys move between items, Home and End go to the first and last. When an item leaves, it shrinks out, the rest glide over, and focus moves to its neighbor.
Code
lane-meter-demo.tsx, the Demo story. The component itself comes from the package.
Reference
Propslanes, max, segments… (9)
Props
| Prop | Type | |
|---|---|---|
lanesRequired | readonly Lane[] | – |
max | numberThe scale shared by lanes without their own | – |
segments | numberCells per lane. default 32 | 32 |
onItemAction | (item: LaneItem, lane: Lane) => voidMakes each item cell a button that calls this. | – |
itemActionLabel | stringThe items' action, spoken with each ("Retry job-8f2a"). Default: the labels' "Retry". | – |
format | Intl.NumberFormatOptionsIntl.NumberFormat options for the values. Default: plain counts. | – |
locale | stringDefault: the YoujProvider locale. | – |
label | stringThe meter's accessible name. Default: the labels' "Queue load". | – |
sound | booleanWith sound on, an item action plays default true | true |
Other props pass through: extends ComponentProps<'div'>. | ||
StylingParts and data attributes
Styling
Parts: lane-meter, lane-meter-lanes, lane-meter-lane, lane-meter-meter, lane-meter-label, lane-meter-value, lane-meter-max, lane-meter-track, lane-meter-cell (with data-state on or off), lane-meter-item, lane-meter-glint, lane-meter-action and lane-meter-tooltip. Each lane has data-tone and, when active, data-active. The labels take the theme's label voice (mono capitals in Basalt). Under 30rem of width, each lane stacks its label and value over the cells.
MotionFill, new value, active lane… · reduced motion
Motion
| Moment | Tokens | ||
|---|---|---|---|
| Fillwhen the meter scrolls into view, each lane lights its cells one after another at a constant rate, a stagger step after the lane above | duration.deliberate560ms | 560ms | |
| New valuelights or darkens the cells between the edge on screen and the new one, in order | duration.fastease.standard140ms · cubic-bezier(0.2, 0, 0, 1) | 140mscubic-bezier(0.2, 0, 0, 1) | |
| Active lanea soft light crosses its lit cells and rests, only while the meter is on screen | duration.deliberate560ms | 560ms | |
| Item leavesshrinks and fades out while the others glide to their new cells | duration.fastease.enter140ms · cubic-bezier(0.16, 1, 0.3, 1) | 140mscubic-bezier(0.16, 1, 0.3, 1) |
Reduced motion
Cells are lit in place, the active lane has no traveling light, and items change at once.
Reduced motion
Every cell is lit at once, the active lane's light is off, and items appear and leave without animation.
AccessibilityKeyboard
Accessibility
- The meter is a
groupnamed bylabel(default "Queue load"). Each lane is ameternamed by its visible label; a lane with its ownmaxis spoken "24 of 32". - Item buttons sit in a group named by their lane. The lane is one tab stop; arrow keys follow the reading direction.
- The cells are hidden from assistive tech; they fill from the inline start, so right to left in RTL.