Azalea
Azalea

Accessibility

What the components already handle, and the four things a caller still has to get right.

Colour is never the only signal

Every place the system uses colour to mean something, it pairs it with a second signal — text, an icon, or a shape.

NEEDS APPROVALDEADThe label is always shown, so the amber and the red do not have to be told apart.
The icon distinguishes a warning from a failure.

One focus ring, everywhere

Identical across every variant on purpose: a keyboard user moving between two Averoa tools should not have to relearn where they are. Tab through these.

light

dark

Labels are bound, not adjacent

Field renders a real <label htmlFor> and wires the hint or error with aria-describedby, so a screen reader announces the problem when focus lands rather than on submit.

No such branch on origin.

Announcements are proportionate

Interrupting a screen reader is a cost, so only failures pay it.

Alert, tone=dangerrole="alert"Interrupts. A failure the reader must know about now.
Alert, other tonesrole="status"Waits for a pause.
FormMessagearia-live="polite"The user just clicked; they are already here. Assertive would talk over them.
Skeletonaria-hiddenThe loading state comes from the region, not from decorative grey boxes.
Avatar imagealt=""The name is already in the row. Announcing it twice is noise.

What the system cannot do for you

Four things that are still the caller's job, and are the four that actually get missed.

  1. Label an icon-only button. <Button size="icon"> with no aria-label is unlabelled to a screen reader — it reads as “button”.
  2. Use a link for navigation. A Button that navigates breaks middle-click, open-in-new-tab and the back button.
  3. Write the error as an instruction. “No such branch on origin” beats “Invalid input” — the component styles it, only you know what would fix it.
  4. Keep the tab order the reading order. Reordering visually with CSS while leaving the DOM alone leaves a keyboard user jumping around the page.

Checking contrast honestly

Every example on this site renders in both themes at once, because a component can look right in the theme you happen to be in and be unreadable in the other — and toggling back and forth from memory will not catch it.

The brand colours are an identity palette, not a UI palette: none of --brand-green, --brand-teal or --brand-blue is guaranteed to carry text at an accessible contrast. Use them for a mark or an accent, and never put body copy on one without checking it.