indicator
indicator marks an element as a decorative representation of state — a check glyph inside a checkbox, the thumb of a switch, the chevron on a disclosure. It is the one part whose job is subtraction: a checkbox already announces “checked” through its control, and a glyph that also exposes itself announces the same fact twice, the second time as noise like “checkmark graphic.”
Status — React: Implemented • Web Components: Implemented • iOS: Not yet planned • Android: Not yet planned
Without it the transform cannot distinguish a glyph that means something from one that merely draws the state, so it must hide all of them or none.
Roles
Apply the following roles to elements:
| Role | Type | Element |
|---|---|---|
indicator | Part | Element of type: container, type: glyph, or type: vector |
| Where | What is emitted |
|---|---|
| The indicator element | aria-hidden="true" |
| The resolved control | Nothing |
Tag, classes, layout, and styling are unchanged — only the attribute is added, so nothing visual changes.
An aria-hidden element must not contain focusable content. An indicator whose subtree holds a slot or an interactive element warns: hiding it would strand the focusable descendant where assistive technology cannot reach it.
Specs
Component anatomy typically has elements and roles like:
anatomy: checkGlyph: type: glyph role: indicatorFigma
Annotate the following layers:
- the state glyph as
role:indicator— the check mark, switch thumb, chevron, or radio dot
Annotate every drawn state layer, not just the obvious one. A switch’s track, handle, and state glyphs are all drawn state and all want the part.
React
Implementation
Nothing. indicator is a declaration the component acts on for itself.
Before / After
// before<span className="check" data-element="checkGlyph" />
// after<span className="check" data-element="checkGlyph" aria-hidden="true" />Contract
None. An indicator is decoration by declaration. An element that needs a handler is not an indicator — it is a button or an increment / decrement part.
Web Components
Identical — aria-hidden="true" on the element inside the shadow root. No host involvement, because the attribute describes the glyph, not the component.
iOS
Not yet planned. Intended binding:
| Emits | .accessibilityHidden(true) |
| Result | VoiceOver skips the glyph; the state announces once, from the control |
Android
Not yet planned. Intended binding:
| Emits | clearAndSetSemantics {} |
| Result | TalkBack skips the glyph; the state announces once, from the control |
Additional details
Resolution
| Accepting control | How it resolves |
|---|---|
Value-bearing (checkbox, radio, switch) | To the component’s single value-bearing control, regardless of tree position |
Non-value-bearing (button, togglebutton, disclosure) | By proximity; ambiguity is an error naming every candidate |
Resolution rarely matters here, because the emission does not depend on which control it resolved to. It matters only for validating that the part is accepted at all.
Where it is consumed instead
radio is the exception: it styles its control directly rather than proxying, so a container-typed indicator is consumed into styling rather than emitted with aria-hidden. A glyph-typed indicator cannot be consumed there and warns.
See also
- checkbox — the control whose state the indicator draws
- radio — where the indicator is consumed into styling instead
- togglebutton — another common host for an indicator
- Roles overview — the vocabulary and how roles are authored