forty-cdk
llms.txt

Primitives

Meter

A gauge that shows a scalar value within a known range, bucketed into quality bands.

forty-cdk/meter WAI-ARIA APG

The gauge reflects data-value against data-min / data-max and reports data-quality, so one rule colours the optimum, suboptimum and critical bands.

72%

Mirrors the HTML5 <meter> element: a measurement (battery, disk space, score, queue depth), not progress on a task. Use Progress for the latter.

When to choose

  • Meter: role="meter", a measurement within a known range, bucketed into quality bands by low / high / optimum. Always determinate, since a meter has no unknown state.
  • Progress: role="progressbar", for a task moving toward completion, including the indeterminate case (value of null). Choose it whenever the number is going somewhere.
  • Slider: when the number is one the user sets rather than one they read.

Anatomy

<div forMeter [value]="diskUsed()" [min]="0" [max]="100" [low]="20" [high]="80" [optimum]="40">
  <div forMeterIndicator></div>
</div>

Examples

Custom value label

getValueLabel receives the clamped value, min and max and returns aria-valuetext, so AT announces 'Disk: 200 GB used · 312 GB free' instead of the bare number.

Disk usage200 GB used · 312 GB free

API

ForMeter

PropertyTypeDescription
value
input
Current measurement (one-way; display-only). Clamped to [min, max] for ARIA / data-* output; the input retains the raw value.
Default: 0
min
input
Lower bound.
Default: 0
max
input
Upper bound.
Default: 100
low
input
Lower boundary of the "comfortable" range.
Default: null (= min)
high
input
Upper boundary of the "comfortable" range.
Default: null (= max)
optimum
input
Ideal point. Drives the quality classification.
Default: null (= midpoint)
getValueLabel
input
Override for aria-valuetext.
Default: —
ariaLabel
input
Accessible name for the meter. Prefer a visible label referenced via aria-labelledby when one exists.
Default: null
Data attributeValues
data-qualityoptimum | sub-optimum | even-less-good
data-valuecurrent value, clamped to [min, max]
data-minlower bound
data-maxupper bound
data-percentagevalue as a number in 0–100

ForMeterIndicator

Visual fill paired with [forMeter]. Mirrors the root's data-* reflections and exposes the --for-meter-percentage custom property so the consumer can drive width / transform from CSS.

Data attributeValues
data-qualityoptimum | sub-optimum | even-less-good
data-valuecurrent value, clamped to [min, max]
data-minlower bound
data-maxupper bound
data-percentagevalue as a number in 0–100

Quality algorithm

The data-quality reflection follows the HTML5 spec:

Optimum sits invalue inQuality
middle[low, high]optimum
middleoutside [low, high]sub-optimum
below lowbelow lowoptimum
below low[low, high]sub-optimum
below lowabove higheven-less-good
above highabove highoptimum
above high[low, high]sub-optimum
above highbelow loweven-less-good

Accessibility

Implements the WAI-ARIA Meter pattern.

  • role="meter" announces the current value as a fraction of the range. Pair with a visible label and aria-labelledby (or set ariaLabel) for context, as in "Disk usage 72 of 100".
  • Inverted bounds are sanitized. If max is passed below min, the reflected range is collapsed to a coherent one (min <= max) so aria-valuemin / aria-valuemax never emit invalid ARIA. The raw min / max inputs read back unchanged.
  • Always determinate. Unlike <progress>, a meter must always have a known value. There is no indeterminate mode in HTML5 / ARIA.
  • Don't use Meter as Progress. Screen readers announce the two roles differently (and assistive guidance differs); pick the right primitive for the meaning.
  • Quality is for CSS only. data-quality is a styling hook; assistive tech reads aria-valuenow / aria-valuetext, not the quality bucket.

Styling

forty-cdk ships no styles: put your own class on each piece and key your CSS off the data-* attributes listed under API, not off the for* selectors (Styling forty-cdk explains why).

CSS custom properties

PropertyMeaning
--for-meter-percentagevalue as a CSS percentage of [min, max] (0%–100%), set on [forMeterIndicator]. Drive width / transform from it.
.indicator {
  width: var(--for-meter-percentage, 0%);
}
.indicator[data-quality='even-less-good'] {
  background: #dc2626;
}

Wrapping in a design system

Subclass the root and re-provide FOR_METER_CONTEXT with useExisting pointing at the subclass, since Angular does not inherit a directive's providers; Wrapping non-form roots walks the pattern.