Ramonda

Accessibility

Two of every five rules ramonda-check runs are about accessibility — thirty-five of eighty-six — and it is the part of the framework that is least visible until you run it. This page says what runs without being asked, what the checker reads, and, at the end, the part none of it can answer.

What you get without asking

An ARIA attribute is written as a string, never as a presence flag. HTML's own booleans work by being there: disabled="" disables a control, and the parser never reads the value — which is why disabled="false" disables it too and is reported. ARIA is the opposite: its attributes are enumerated strings, so an aria-hidden written with no value is not aria-hidden="true" — the empty one means neither true nor false, and the element stays exactly where it was.

<div aria-hidden={true} />             {/* aria-hidden="true" */}
<button disabled={true}>Save</button>  {/* disabled=""        */}

The framework keys this on the NAME rather than on the value being a boolean, so both are right without you thinking about it.

A form field's bind carries aria-invalid. Spreading it onto a control announces the field's validity along with its value, so a message a sighted reader sees is a state a screen reader reports. See bind.

What the checker reads

Thirty-five rules, in seven groups. Each has its own page with what it reports and what to write instead.

Nothing to announce it by — the element exists and has no accessible name.

ARIA written, and doing nothing. This is the group with the sharpest failure mode: the browser keeps whatever you write. An attribute is a string, so a misspelled name, an invented role and a value outside the specification all reach the inspector looking perfectly healthy and none of them does anything.

ARIA fighting the element it is on. A written role always wins, so a role can take away what the tag already supplied.

Hidden from the tree, and still reachable. The worst of the three: an element a screen reader cannot see and a keyboard can still land on, so the focus disappears into nothing.

The keyboard. A click handler works for a pointer and for nothing else.

The shape of the page, which is how somebody who cannot see it navigates.

Ids, because ARIA is built on them. aria-labelledby is a reference, and a reference to nothing announces nothing.

Every one of them fails your build

There is no warning level. An accessibility rule reports a fault exactly as the rule for an async render() does, and a reported fault fails the command.

That is deliberate, and the reason is what a warning actually does: it is read once and then not read at all. Thirty-five of them printing under a passing build is thirty-five things nobody has to decide about.

Where a rule is wrong about your markup, say so on the line:

// ramonda-check-ignore this div is a backdrop; the real exit is the button beside it
<div className="scrim" onclick={this.close} />

The reason is mandatory — an empty directive is itself reported — and every annotated site is printed back on every run with the words its author wrote. So an exception is a decision somebody made and can be asked about, which is more than a warning ever was. See how to say "not here".

What it cannot see

This is the half worth reading twice, because a green run is easy to mistake for an answer.

An element that spreads props is left alone entirely. <img {...rest} /> may carry the very attribute a rule is looking for, and nothing here can know. Silence on a spread is not approval.

A value it cannot resolve is not judged. <div role={kind}> is a role the checker cannot read, so the rules about roles say nothing about it. The same is true of an id built at runtime, an aria-label from a translation call, a tabIndex from a prop.

And the part no tool answers at all. Every rule here is about markup that is provably wrong — a name that is absent, a role that contradicts its tag, a reference to an id nothing declares. None of them can tell you whether the announcement makes sense, whether the reading order matches what the page means, or whether somebody can actually complete what they came to do. That needs a keyboard, a screen reader, and somebody using them.

The checker's job is to take the mechanical mistakes off the table so the time goes to that.

Next

  • Rules — all eighty-six, including the thirty-five above.
  • Checking your app — how to run it, and what it proves that a running page cannot.
  • bind — the one place the framework fills in an ARIA attribute for you.