DocumentationComponentsTheme Creator
Theme CreatorGitHubIntroduction
InstallationUsageThemingMotion
Components
ButtonIconButtonLinkLabelBadgeStatusChipAvatarShortcutSpinnerSkeletonProgressMeter
AI agentsContributing
  1. Components
  2. Meter

Meter

Gauge displaying a known value within a fixed range — battery, disk usage, score, capacity. Linear, circular or an open 180°/270° arc, a fill or a marker, qualitative colour zones, full intent palette with optional threshold-based auto-coloring, locale-aware formatting, and a multi-segment MeterGroup variant for stacked usage.

$ pnpm add @tessinaui/ui

When to use

  • A known value within a fixed range. Battery, disk usage, a score out of five, seats used: the value already exists and will not change while the user waits.
  • A value that should change colour as it crosses a limit. thresholds recolour the meter, and marks and zones show where a goal, a limit or a healthy range sits.
  • A reading of capacity. MeterGroup stacks parts of a whole, such as storage by type, with a legend and an optional remaining entry.
  • A compact reading in a row or a table cell. xs with labelPosition="none" gives a dense in-cell meter; the label still names it.
  • A gauge. type="circular" gives a ring, and sweep opens it into a 270 or 180 degree arc with end labels.
  • A value with a visible label and number. Show the formatted value beside the bar so the reading never depends on colour alone.

When not to use

  • For work in flight. An upload, a multi-step form or a page load moves toward done: use Progress, which can also be indeterminate (Meter vs Progress).
  • For a quantity with no meaningful maximum. A meter needs a range; show the number instead (Empty and unknown).
  • To let people set a value. A meter is a static reading with no keyboard interaction; use Slider.
  • For a trend or a comparison across many items. Use a Chart.
  • For content that is still loading. Use Skeleton or Spinner.
  • For steps in a flow. Show position with a segmented Progress or a "Step 2 of 4" caption.

Installation

Terminal
pnpm add @tessinaui/ui

Usage

example.tsx
import { Meter, MeterGroup } from "@tessinaui/ui";
example.tsx
{/* Basic */}
<Meter value={68} label="Storage" />

{/* Circular */}
<Meter type="circular" value={72} label="CPU" valuePosition="inside" />

{/* Threshold-based auto colour */}
<Meter
  value={92}
  label="Disk usage"
  thresholds={[
    { at: 50, intent: "none" },
    { at: 80, intent: "warning" },
    { at: 101, intent: "error" },
  ]}
/>

{/* Locale-aware formatting */}
<Meter
  value={186.4}
  max={500}
  label="Disk"
  format={{ style: "unit", unit: "gigabyte", maximumFractionDigits: 1 }}
/>

{/* Custom range — rating */}
<Meter value={4.3} max={5} label="Rating" intent="success" showFraction />

{/* Multi-segment */}
<MeterGroup
  max={500}
  showTotal
  format={{ style: "unit", unit: "gigabyte", maximumFractionDigits: 1 }}
  segments={[
    { label: "Photos", value: 124,  intent: "success" },
    { label: "Videos", value: 86.5, intent: "error"   },
    { label: "Music",  value: 42.3, intent: "info"    },
    { label: "Other",  value: 31.2, intent: "none"    },
  ]}
/>

Examples

Default

A basic linear meter with a label and right-aligned value.

Sizes

Five track heights — xs, sm, md, lg, and xl. xs is the hairline rule that reads as part of a dense row rather than as a bar of its own.

Intents

The house intent vocabulary: none (the neutral default), info, success, warning, error.

Thresholds

The indicator recolors itself as the value crosses breakpoints — error, then warning, then success.

Circular

The ring variant with the value centered inside via type="circular" and valuePosition="inside".

Arc gauge

sweep={270} or sweep={180} opens the ring into a gauge. The opening is always centred at the bottom, and minLabel / maxLabel sit under the two terminals. A 180 gauge crops its box to the upper half, and an inside value settles at the bottom of the arc.

The sweep runs clockwise in every locale, RTL included — gauges and clocks don't mirror, so the minimum stays on the left terminal. Only the label text follows dir.

Gauge

One value against a known range, read by its band. zoneStyle="current" draws only the band the value is in: the ring and a faint track take its colour, and its name sits under the number. Press the buttons and the figure counts on the ring's own curve; the colour and the band's name change as the count crosses a boundary, not when it lands. fillOnView fills the ring once, when half of it is on screen. At the ends of the range each button stays focusable and reports itself unavailable, so a keyboard user is never sent back to the page.

Gauge with zones

A fill over zones is a ring: the zones' own colours, dimmed, are the track, and the ring is lit up to the value in those same colours, blending from one zone into the next and rounding off where the value is. It grows on the count. A thin seam marks each boundary, so no zone rests on colour alone. With no intent or thresholds, the meter takes the intent of the zone the value sits in; on a ring the zone's name sits under the number, and a half dial — with no room under its value — names it with the status glyph. indicator="marker" lights every zone at full colour instead and reads the value with a dot.

Lit dial

indicator="marker" over zones lights the whole scale at full colour, blending from one zone into the next without a break, and a dot cut into the arc — the dial's own colour where it stands, with the arc broken clean on either side — reads the value. On a 270° ring at lg or xl the icon sits in the ring's opening, in the current band's colour. The band's name under the number says the state in words.

Segmented zones

zoneStyle="segmented" draws the scale as a tick dial: one tick every 6° of the sweep, each in the colour of the zone it falls in. Ticks light up to the value — one by one as the figure counts — and the rest stay on the track, so the lit count is the reading and the change of colour is the boundary.

Multi-segment

A MeterGroup stacks several colored segments into one bar with a legend and total.

Storage breakdown

showRemaining names the unfilled part of the track. "How much is left" is the number a storage or seat meter actually gets read for, and it is the one a stacked bar cannot show on its own.

Disk usage

A MeterGroup reads as one shape cut into parts: a 1px seam of the ground separates neighbouring segments. remainingPosition="track" prints what is left in the empty part of the bar instead of the legend, totalText turns the header's fraction into a sentence, and legendValues={false} leaves the legend as names with their swatches.

Status and icons

icon puts a glyph in the label row. The status glyph is automatic whenever thresholds are in play (or the intent is error/warning) and the meter shows a label, so the state is never carried by fill colour alone — see Contrast below. It captions the label, so a label-less meter shows colour and value text only; pass statusIcon to force it, or statusIcon={false} to opt out.

Target marks

marks places static reference ticks on the track — a goal, a budget, a limit.

Scale labels

minLabel and maxLabel name the ends of the range. Describe the current value and both endpoints; a screen reader reads the visible labels.

Marker

indicator="marker" shows the value with an indicator that sits at it, instead of a fill that stops at it. It is the line between a standard gauge and a capacity gauge. Use a marker when the position matters more than how much is used: a temperature, a score, a reading on a scale.

The marker is foreground ink on a background halo, not an intent colour, so it stands out against the bare track and every zone colour. It travels the track minus its own width, so it stays inside the bar at min and max.

Colour zones

zones paints qualitative regions along the scale: under, healthy, over. Each zone's from defaults to the previous zone's to, and the last zone runs to max. A tick marks every boundary and label captions a zone, so the bands are never told apart by colour alone.

Zones sit under a fill too. There they are a 30% wash and the fill takes the zone the value reached. Under indicator="marker" the zones are the whole scale and the marker reads it, so they paint at full strength.

zonesthresholds
What changesStatic regions painted along the whole trackThe fill's colour, by the current value
Reads as"Where does the value fall?""What state is the value in?"
Togetherthresholds (or an explicit intent) decide the meter's intent; zones stay painted—

Segmented

segments renders the track as N discrete cells that fill completely, never partially. This is the shape a battery, a signal strength or a password meter wants — distinct from MeterGroup, which divides one bar proportionally.

Password strength

The canonical segmented meter: a 0–4 score (the range zxcvbn returns) across four cells, with the strength stated in text rather than by colour alone.

Quota and over-capacity

A value above max clamps the bar — aria-valuenow must stay inside the range — but the text stays truthful and the root carries data-exceeded.

Caption row

description is the helper line under the track. With valuePosition="below" it shares that row: helper at the start, value at the end.

Value positions

right (default), below, inside and none. inside needs a track tall enough to hold text, so at xs–md it falls back to right rather than dropping the value.

Formatting

format and locale take Intl.NumberFormat options. Whatever the meter shows, it announces the same thing — see the accessibility note below.

Comparison list

Several meters in a row with aligned label and value columns — the most common shape a meter appears in.

In a table

xs plus labelPosition="none" gives a dense in-cell meter. The row already names the thing, so the meter takes its accessible name from label without drawing it.

Empty and unknown

Zero renders an empty track; a tiny nonzero value still paints. A quantity with no meaningful maximum is not a meter at all — ARIA says so — so show the number instead.

Loading

MeterSkeleton takes the same type, size and sweep, so a loading gauge has the same box as the gauge it stands in for.

On color

Inside a Surface, Meter and MeterGroup inherit tone="on-color": the track, ticks, marker and text derive from the plate's ink, and an intent paints the plate's own intent ink rather than the page colour. On the primary, foreground and warning plates the intents keep their hue; on the error, info and success plates no hue is legible, so every intent takes the plate's ink — the status glyph and the value text still say which state the meter is in, and MeterGroup separates its segments with a seam of the plate and gives each one a texture — solid, two hatches, dots — that its legend swatch repeats. A linear inside value moves to the header row on a plate, as Progress's does. Pass tone="on-color" yourself only on a plate something else paints; an explicit tone always wins.

RTL

Under dir="rtl" a linear meter mirrors, so the fill, marker and scale start at the right. A circular gauge does not: it turns clockwise in every locale, and its terminal labels stay put. Leave dir unset and the meter follows the page.

API Reference

Meter props

PropTypeDefaultDescription
valuenumber—The current value (clamped between min and max)
minnumber0Minimum
maxnumber100Maximum
type"linear" | "circular""linear"Bar or ring
size"xs" | "sm" | "md" | "lg" | "xl""md"Size token
rounded"none" | "sm" | "md" | "lg" | "full""full"Corner radius (linear only — a ring has no corners)
intent"none" | "error" | "warning" | "success" | "info""none"Semantic meaning (§1). none renders the neutral primary fill
variant"solid" | "soft""solid"Visual weight — soft paints a *-light trail and ends it with a foreground edge, which carries the value
tone"default" | "on-color"inheritedSet on a coloured or dark plate — track, marker and text derive from the plate's ink, and an intent paints the plate's own intent ink. Inherited from a surrounding Surface; an explicit value wins
thresholdsArray<{ at: number; intent: MeterIntent }>—Auto-recolor based on value crossing breakpoints
labelReactNode—Visible label rendered above (linear) or below (circular) the meter
labelPosition"outside" | "none""outside"Whether the label is drawn. It still names the meter when hidden
valuePosition"right" | "below" | "inside" | "none""right"Where the formatted value renders. inside falls back to right below lg, on a marker track, and on a linear meter under tone="on-color"; with segments it sits in the last filled cell
showFractionbooleanfalseRender as ${value}/${max} instead of ${value}
formatIntl.NumberFormatOptionspercent of rangeLocale-aware formatting (currency, units, compact). Without it the value reads as its percent of the min–max range — 712 on 300–900 is 69%
localeIntl.LocalesArgumentruntimeBCP-47 locale tag
renderValue(formatted: string, value: number) => ReactNode—Fully custom value rendering — overrides format / showFraction
getAriaValueText(formatted: string, value: number) => string—What assistive tech announces. Required alongside renderValue
descriptionReactNode—Helper line under the track. Optional, except on an error state
iconReactNode—Leading glyph in the label row
statusIconReactNode | booleanautoStatus glyph, rendered beside the label. Defaults to the resolved intent's glyph when thresholds are in play or the intent is error/warning and a label is visible; true forces it without one, false opts out
minLabel / maxLabelReactNode—Scale endpoint labels under the track
marksArray<{ at: number; label?: ReactNode }>—Static reference ticks — a goal, a limit, a target
segmentsnumber—Render the track as N discrete cells that fill completely (linear only)
sweep360 | 270 | 180360How much of the circle a type="circular" meter draws. 270 and 180 are open gauges with minLabel / maxLabel under the terminals. Always clockwise
indicator"fill" | "marker""fill"A fill that stops at the value, or a marker that sits at it. Ignored under segments
zonesArray<MeterZone>—Qualitative regions painted along the scale, with a tick at every boundary. Ignored under segments
zoneStyle"continuous" | "segmented" | "current""continuous"How zones draw on a ring: one dim track with the reached part lit in the active zone's colour and a ring on its head; a tick dial — a tick every 6° in its zone's colour, lit up to the value; or only the current zone — the ring and a faint track in its colour, its label under the number
fillOnViewbooleanfalsetype="circular": the ring rests empty until half of it is on screen, then fills once while the figure counts. aria-valuenow holds the value throughout; reduced motion lands on it at once
childrenReactNode—Custom content centred in the ring (type="circular")
dir"ltr" | "rtl"inheritedText direction
classNamestring—Additional classes on the root

MeterZone

FieldTypeDescription
intentMeterIntentThe zone's colour, painted as a 30% wash so the marker or fill reads above it
fromnumberWhere the zone starts, on the min–max scale. Defaults to the previous zone's to (the first zone starts at min)
tonumberWhere the zone ends. Defaults to max
labelReactNodeCaption centred under the zone (linear)

Deprecated, one minor. intent="primary" and intent="neutral" both render as none (they were measured identical in dark and near-identical in light), and tone="solid" / tone="soft" is the old name for variant — §1 gives tone to default | on-color, and the two value sets never overlap, so one prop carries both until the alias goes. Both still work and dev-warn once.

Thresholds

thresholds lets the meter recolour itself based on the current value. The lowest at whose value is greater than the current value wins. If no threshold matches, the base intent is used. at is on the meter's own min–max scale, like marks — a 90% threshold on a 0–10 meter is at: 9.

example.tsx
<Meter
  value={92}
  thresholds={[
    { at: 30, intent: "error" },     // 0–29  → error
    { at: 70, intent: "warning" },   // 30–69 → warning
    { at: 101, intent: "success" },  // 70–100 → success
  ]}
/>

For an inverted scale (e.g. battery — low is bad), reverse the order:

example.tsx
<Meter
  value={15}
  thresholds={[
    { at: 20, intent: "error" },
    { at: 50, intent: "warning" },
    { at: 101, intent: "success" },
  ]}
/>

MeterGroup props

PropTypeDefaultDescription
segmentsArray<MeterGroupSegment>—Stacked segments that fill the bar
minnumber0Minimum value of the scale
maxnumber | "sum"100Max value, or "sum" to derive from segment values
size"xs" | "sm" | "md" | "lg" | "xl""md"Size token
rounded"none" | "sm" | "md" | "lg" | "full""full"Track corner radius
tone"default" | "on-color"inheritedOn a plate each segment paints its intent's plate ink, a seam of the plate separates neighbours, and each segment carries a texture its legend swatch repeats. Inherited from a surrounding Surface; an explicit value wins
labelReactNode—Label rendered above the bar — also the accessible name
legendPosition"above" | "below" | "none""below"Where to render the segment legend
showTotalbooleanfalseRender ${total} / ${max} next to the label
totalText(used, max) => ReactNode—The header's reading as a sentence — `${used} of ${max} used` — from the formatted total and maximum. Needs showTotal
showRemainingbooleanfalseShow the unfilled part of the track as "remaining". Ignored when max="sum"
remainingLabelReactNode"Remaining"Label for the legend entry
remainingPosition"legend" | "track""legend"Where the remainder is printed: a legend entry, or its number centred in the empty part of the bar (and no legend entry)
legendValuesbooleantruePrint each segment's value in the legend. false leaves names and swatches
formatIntl.NumberFormatOptions—Format the total + each legend value
localeIntl.LocalesArgumentruntimeBCP-47 locale tag
dir"ltr" | "rtl"inheritedText direction

MeterGroupSegment

FieldTypeDescription
valuenumberSegment value (in same scale as min/max)
labelReactNodeDisplay label in the legend
intentMeterIntentColour for this segment (default "none")
variant"solid" | "soft"Visual weight (default "solid"). A soft segment ends in a hairline edge and its legend dot is outlined
tone"solid" | "soft"Deprecated alias of variant. The group's surface tone is MeterGroup's own tone
iconReactNodeOptional icon next to the legend label

Motion

  • One spring drives the fill and the figure. The fill, ring, needle and marker run on the panel curve (a critically damped spring, no overshoot, about half a second), and the visible number counts on that same curve, so it never reads ahead of or behind the bar. aria-valuenow and aria-valuetext always hold the real value; only what is drawn counts.
  • A changing label crosses over. When a text label changes with the reading ("Storage" to "Storage almost full"), the new text fades in as the old fades out in the same line; the outgoing copy is hidden from assistive tech and is gone once its fade has run. A label that is a node is left as given.
  • The band is named in words. On a ring (270° or full) at xl with valuePosition="inside", the active zone's text label shows under the number in the zone's own ink and crosses over when the value moves into another zone. A half gauge has no room under its centre line; it keeps the zone ticks and the label row.
  • The ring changes band as the count crosses. The fill's colour and the band's name follow the counted figure, so they switch at the boundary on the way, not when the count lands. What assistive tech reads changes at once.
  • Fill on view. With fillOnView the ring rests empty until half of it is on screen, then fills once on the same curve. It happens once per mount; later values simply spring to their place.
  • A changing detail crosses over. A text description ("14 of 20 checks passing") fades across like the label.
  • Full is not "done". Unlike a progress bar, a meter does not turn to success at its maximum: it reads against a limit, so full can mean exhausted. Colour stays with intent, thresholds and zones.
  • Reduced motion: the fill and the figure jump to the new value, the label and detail swap at once, and a fillOnView ring shows its value from the start.

Notes

  • Inside value — only lg and xl linear sizes render an inline value; below that, and on a marker track, it falls back to right rather than dropping the value, and so does a linear meter on a coloured plate, bar or cells, where the fill is the plate's ink. With segments it sits in the last filled cell (the first cell when none is), and only that cell grows if the value would not fit. The fill never gets narrower than its own value, so at low values it runs a little ahead of the true extent rather than clipping the number; at exactly 0 no fill is painted and the value sits on the track in the foreground colour.
  • RTL — a linear meter fills from the right. The track uses logical positioning (inset-inline-start), so the fill, marks and their captions, zones, the marker and discrete cells all start at the inline start with no transform flip, and the inside value reads normally. A circular meter or arc gauge is not mirrored: circular indicators turn clockwise in every locale, and an arc gauge's terminal labels stay on their terminals.
  • max="sum" on MeterGroup — convenient when you want the bar to be exactly as long as the data fills it (e.g. a triage panel showing exact bug counts), rather than a fixed scale.
  • segments means two different things, deliberately: on Meter it is a number of discrete cells (the Progress-family meaning), and on MeterGroup it is the array of proportional parts.

Meter vs Progress

The two components look similar but communicate different things:

MeterProgress
PurposeA known value within a fixed rangeTask completion working toward 100%
ExamplesBattery 78%, Disk 320 GB / 512 GB, Score 4.2 / 5, RAM 6.2 GB / 16 GBFile upload, multi-step form, page load
RangeCustom min / max (default 0–100)Always 0–100
IndeterminateNo — value must be knownYes — indeterminate prop
ARIA rolerole="meter"role="progressbar"

Use Meter when the value already exists and isn't going to change as the user waits. Use Progress when something is loading.

Accessibility

Pattern: WAI-ARIA Meter.

  • One role="meter" per reading. Meter is built on @base-ui/react/meter and renders role="meter" with aria-valuemin / aria-valuemax / aria-valuenow (clamped into the range) / aria-valuetext. MeterGroup puts the role on the whole bar, never on a segment, and takes its name from label.
  • A meter needs a name. The visible label supplies it; with labelPosition="none" or no label, pass aria-label. An unnamed meter warns in development.
  • Locale-aware aria-valuetext — it carries the same Intl.NumberFormat text the meter shows: the percent of the min–max range by default, or the value in your format.
  • Every descendant of a meter is presentational. ARIA forces role="presentation" on everything inside role="meter", so the visible value is not announced on its own — it only reaches assistive tech through aria-valuetext. showFraction and format handle this for you; if you pass renderValue, pass getAriaValueText with it or the screen and the screen reader will disagree (development warns when you don't).
  • A meter is not focusable and carries no keyboard interaction, no aria-live and no interactive children — a meter is a static reading, and a control inside one is unreachable. For work in flight use Progress.
  • Colour is never the only signal. When thresholds are in play and a label is visible, the status glyph renders automatically, because several intent fills do not clear the 3:1 non-text contrast floor against the track — see Contrast. A label-less meter leans on its value text instead, so keep that visible.
  • We render div[role="meter"], not the native <meter> element. MDN's stated best practice is the native element, but it is effectively unstyleable across engines (::-webkit-meter-* only) — which is why Base UI and the other headless libraries all make the same deviation.

Keyboard

KeyBehaviour
—None. A meter is not in the tab order and handles no keys

Contrast

Meter's fill inherits the shared intent tokens and its track is bg-secondary, and several of those pairs do not clear the 3:1 that WCAG 1.4.11 asks of a meaningful graphic. Measured on the live component, both themes:

FillLightDark
none (primary)14.2:114.5:1
info4.1:15.7:1
error3.8:12.8:1
success2.6:16.8:1
warning1.7:18.9:1
variant="soft" trail, any intent1.2:11.0:1
variant="soft" leading edge15.7:114.5:1

Light-theme amber cannot reach 3:1 against the track even at full saturation, so this is not a tuning miss — it is the same physics the design system already records for the amber presence dot. Two consequences for consumers:

  1. Never let the fill be the only carrier. Keep the value text visible, or keep the automatic status glyph. Both are on by default — but the glyph needs a visible label, so a label-less meter must keep its value text (or set statusIcon).
  2. In variant="soft", the edge carries the value, not the tint. The *-light trail cannot reach 3:1 in any intent or theme, so a soft meter ends its fill with a solid foreground edge. At the minimum value there is no fill and no edge, so an empty soft meter still relies on its value text.

Retuning the shared tokens is a system-level decision, tracked separately.

Zones and markers

Zones are a 30% wash of their intent colour, and they are told apart by their boundary ticks and captions, not by their tints. The marker is foreground ink rather than an intent colour for the same reason. Measured on the live gauge and bar, both themes, as the lowest pair across every zone:

PairLightDark
Marker vs track15.7:114.5:1
Marker vs any zone9.3:17.1:1
Boundary tick vs the zone under it4.0:13.7:1
Zone wash vs track1.2:11.3:1
Solid fill vs the zones it covers1.0:14.4:1

A zone's wash does not clear 3:1 against the bare track, and nothing tuned within a wash can. That is why every boundary carries a tick. A fill over zones is worse: it can match its own zone's wash almost exactly. The tick, the value text and the automatic status glyph still carry the state, but if position is what matters, use indicator="marker".

On a coloured plate

With tone="on-color" every pair derives from the plate's own ink, so the floor is set by the plate: the error, info and success plates carry the least ink contrast. Measured by computed colour on the six Surface plates, both themes, as the lowest pair across plates and intents:

PairLightDark
Label, value, description, glyph vs plate4.8:15.4:1
Solid fill or MeterGroup segment vs track3.6:13.9:1
variant="soft" leading edge vs track3.7:14.0:1
Marker or boundary tick vs its halo4.8:15.4:1
Track vs plate1.2:11.4:1

On the error, info and success plates no intent hue is legible, so every intent takes the plate's ink. There the status glyph and value text name the state, and each boundary tick sits on a halo of the plate because it is the only thing that separates one zone from the next. In a MeterGroup a seam of the plate separates the segments, and each segment's texture is repeated on its legend swatch, so an entry names its segment without colour. The track is a 20% wash of the plate's ink — as faint against the plate as the page track is against the page — and every fill clears 3:1 against it.

AT matrix

ATStatus
VoiceOver + Safari (macOS)Passed 2026-09-14. Each meter reads its value against the range, then its name and role: "68 of 100, Storage, level indicator", "9 of 10, Seats used, level indicator". Transcript: tests/qa/vo-transcripts/meter.md
VoiceOver + Chrome (macOS)UNTESTED
NVDA + Chrome (Windows)UNTESTED — no Windows host available
JAWSUNTESTED

NVDA and JAWS stay untested until a Windows host exists (QA flow §5.6).

ProgressButtonGroup

On this page

When to useWhen not to useInstallationUsageExamplesDefaultSizesIntentsThresholdsCircularArc gaugeGaugeGauge with zonesLit dialSegmented zonesMulti-segmentStorage breakdownDisk usageStatus and iconsTarget marksScale labelsMarkerColour zonesSegmentedPassword strengthQuota and over-capacityCaption rowValue positionsFormattingComparison listIn a tableEmpty and unknownLoadingOn colorRTLAPI ReferenceMeter propsMeterZoneThresholdsMeterGroup propsMeterGroupSegmentMotionNotesMeter vs ProgressAccessibilityKeyboardContrastZones and markersOn a coloured plateAT matrix