Components / data

Meter

Built as a div with role="meter" rather than a native <meter>, because the native element cannot be styled to the contract across the browser floor.

Rendered from the package · open on its own

Summary

A measurement inside a known range — storage used, budget spent, sections completed.

APG patternMeter
Built onnative elements
Statusstable
Since0.1.0
<Meter id="storage" label="Storage" value={3.2} max={10} valueText="3.2 GB of 10 GB" />
<Meter id="sections" label="Sections filled in" value={4} max={7} intent="positive" />

Anatomy

A <div data-se="meter"> with a header and a track. track carries role="meter" and the aria-value* set.

PartElementRequired
fill<div>yes
header<div>yes
label<span>no
track<div>yes
value<span>yes

Properties

PropertyValuesDefaultWhat it does
valuenumberrequiredThe current reading. Clamped to min and max rather than rejected, because a meter that renders nothing tells the reader less than one that renders full.
minnumber0The bottom of the range.
maxnumber100The top of the range. A meter is meaningless without a known ceiling — that is what separates it from a count.
labelstringnoneDrawn beside the bar and used as the accessible name.
valueTextstringnoneOverrides the computed percentage — use it for "3.2 GB of 10 GB".
intentaccent · positive · negative · warningaccentThe meaning of the reading, not decoration. Use negative when the level is a problem the reader should act on, never merely because the bar is nearly full.
idstringnoneOptional. A stable id is generated when omitted; the name never depends on it.

States

_None. Rest is the only condition it has._

Behavior

The fill tracks the value, up or down.

Accessibility

The value is always written beside the bar. A bar alone cannot be read by a screen reader and cannot be read precisely by anyone at all.

useId supplies the id when none is given, because a label wired to an id the consumer had to remember is an accessible name the consumer will forget.

Keyboard

None of its own. It is not focusable and takes no keys.

Roles, states and properties

AttributeSet by
aria-labelset at render
aria-labelledbyset at render
aria-valuemaxset at render
aria-valueminset at render
aria-valuenowset at render
aria-valuetextset at render
rolealways meter

Focus

Never takes focus. It reports a value and offers no action.

Screen reader

Not recorded as verified. Stage 4 of the readiness ladder — driving each component with VoiceOver and NVDA — is unstarted across the package, and no component should claim otherwise until docs/journal/ records the session that did it.

Contrast and target size

npm run check:contrast audits every color pair this component uses across all four skins, light and dark, and fails the build on a shortfall. Two waivers are on the record in docs/audit/DEFERRED.md.

It sets no target size of its own; anything interactive inside it brings its own.

Tested

  • test/apg/partials-sweep.test.jsx

Known gaps

_No upstream requirement is recorded as not applicable._

Appearance

TokenUsed for
--se-accentintent
--se-duration-mediumtransition
--se-ease-standardtransition
--se-font-codefont-family
--se-negativeintent
--se-positiveintent
--se-radius-pillborder-radius
--se-space-2block-size, gap
--se-space-3gap
--se-surface-sunkbackground
--se-textcolor
--se-text-mutedcolor
--se-text-smfont-size
--se-warningintent

Shared with Progress, so the two cannot drift apart visually while staying apart semantically.

Motion

The fill crosses --se-duration-medium when the value changes.

Content

Pass valueText whenever the raw units mean more than a percentage. 3.2 GB of 10 GB is what a reader wants.

Usage

Not a progress bar. A meter reports a level that can fall again; progress only ever fills. If the number can go down, this is the right component.

intent is for the meaning of the reading, not decoration. negative when the level is a problem the reader should act on — never merely because the bar is nearly full.

Notes

Built as a div with role="meter" rather than a native <meter>, because the native element cannot be styled to the contract across the browser floor.