Circular Progress Bar

How the Circular Progress Bar works with a keyboard and assistive tech, and where it stands against WCAG 2.2 AA.

FreeReact and Vue
AAWCAG 2.2 target
2/3contrast pairs passing
1keyboard interactions

The Circular Progress Bar is a drawing: an SVG with role="img" named by aria-label, such as "Battery half full". It shows one of three states, not an exact value, so the label should say which. Without a label it is aria-hidden, and the value belongs in the readout in its middle or in text next to it.

Keyboard#

Tab

Passes over the gauge: it is not focusable.

Semantics#

role="img"

Read as one image.

Always
aria-label

Say the state in words: "Gauge half full", "Charge complete".

Labelled
aria-hidden

Decorative; the ticks or bars are never read one by one.

No label

Colour contrast#

Every variant and state has to meet WCAG 2.2 Level AA. Measure the colours as they land on screen: a translucent hover or press wash over whatever sits behind it.

3:1

Fill · Filled marks against the page

The filled ticks carry the state, so they need 3:1 against the surface and against the empty ticks beside them. The empty ticks are a guide and need not.

WCAG 1.4.11 Non-text Contrast ↗

Measured contrast#

Filled and empty ticks against a white page and against each other, from the gauge's tokens. Ticks are graphics and are held to 3:1; the empty track is a guide and is expected to fall short. 1 of 3 pairs fall below their minimum (4.5:1 for text, 3:1 for graphics) and are marked in amber.

PartFilledEmptyFilled vs empty
Ticks · Against white5.40passes1.34below the minimum4.03passes

Motion#

  • The gauge does not move. Changing state swaps the drawing at once.

Checklist#

Always pass aria-label, or hide it and give the value in text.

Put the value in the middle as text, so the state never rests on the ticks alone.

When the readout says the value, hide the ring (no aria-label) so it isn't read twice.