Accessibility for an agent building and testing interfaces
The conformance level, what gets verified and how, and the failures an agent introduces without noticing.
- Authors
- Leon Mallett, Founder of Captivated Ltd with Claude Code
- Status
- Last confirmed working 21 August 2026 on Claude Code 2026-08
- Written
- 21 August 2026
- Licence
- Handover-1.0
Customise before downloading
This document has 2 fill-in fields. Complete them and you get a copy ready to commit, rather than one to edit afterwards. Nothing is sent anywhere — the file is assembled in your browser.
The conformance level this project holds itself to. Shared with the design system rootnote.
What is actually tested against, rather than what is theoretically supported.
A customised copy is a derivative of the published document: its contents differ, so it carries a line naming the original. Any field you leave blank keeps its{{placeholder}}, so it stays obvious rather than silently empty.
What this project commits to, what gets verified, and where an agent should stop. The design system rootnote covers the component-level rules; this covers the commitment itself and how it is checked.
Why an agent needs this stated
Accessibility failures are the class of defect most likely to reach production, because they are invisible to the person who introduced them. Code that is unusable by keyboard looks perfect to someone using a mouse. A control with no accessible name reads identically to one that has one, unless you are listening rather than looking.
An agent has the same blind spot, and a worse one: it produces markup that looks correct and is semantically empty. The specific failures, all of which pass review:
- A div with a click handler instead of a button. It looks right, works with a mouse, and is unreachable by keyboard and invisible to a screen reader.
- An icon-only control with no accessible name, which announces as “button” and nothing else.
- A focus outline removed because it looked untidy in a screenshot.
- A colour-only status indicator — the red row, the green tick — which carries no information for anyone who cannot distinguish them.
- A modal that does not trap focus, so keyboard users tab into the page behind it and never find their way back.
- Form inputs with a placeholder instead of a label, which disappears exactly when someone needs it and is not announced as a label at all.
None of these are exotic. All of them are the default output of building for how it looks.
The commitment
Standard: {{accessibility_standard}}. Not aspirational — this is the level work is expected to meet, and falling short of it is a defect rather than a future improvement.
Tested against: {{assistive_tech_support}}. State what is genuinely tested rather than what is theoretically supported. “Works with screen readers” is a claim nobody has verified; naming the specific combinations is one somebody can.
What to check, and how
Automated checks catch perhaps a third of it. Run them — they are cheap and they find contrast failures, missing names and structural problems reliably. Then stop believing them, because the things they cannot detect are the things that make a product unusable: whether focus order makes sense, whether an announcement is comprehensible, whether an interaction is completable without sight.
Keyboard-only is the highest-value manual check and takes a minute. Put the mouse down and complete the task. You are checking that everything interactive is reachable, that focus is always visible, that focus order follows the visual order, that nothing traps focus except a modal that should, and that the modal returns focus where it came from.
Then listen to it. Turn on a screen reader and complete the same task. This is uncomfortable the first few times and it is the only way to discover that your carefully-labelled control announces as “button button”.
Zoom to 200% and reflow to a narrow viewport. Content must not be cut off or require horizontal scrolling. This overlaps almost entirely with responsive design and finds different bugs than a device emulator.
Semantics before everything
Use the element that means what you mean. A button that does something is a button. A link that goes somewhere is a link. This single rule prevents most of the failures above for free, because native elements arrive with keyboard behaviour, focus handling and announcements already correct.
ARIA is for what HTML cannot express, not a way to make the wrong element behave. A div with a role and a tabindex and a key handler is reimplementing a button badly. The rule of thumb is real: no ARIA is better than bad ARIA, because incorrect ARIA actively lies to assistive technology, whereas absent ARIA merely under-describes.
Headings describe structure, not size. Screen reader users navigate by heading. Skipping a level to get a smaller font is a navigation bug with a visual cause; use a heading level that is correct and style it.
Every input needs a real label, programmatically associated. Placeholders are not labels.
Content is part of it
- Link text describes its destination. “Click here” and bare URLs fail for anyone reading links out of context, which includes every screen reader user and most people scanning.
- Images need alternative text that carries the same information — and decorative images need empty alternative text, not a description, so they are skipped rather than announced.
- Do not convey meaning by position alone, since position is a visual property.
- Captions and transcripts for anything with audio.
Where to stop and ask
- Relaxing any of the above. An accessibility rule is a commitment with legal weight in most jurisdictions, and it is never a tidiness matter. If a rule is blocking something, that is a conversation.
- Shipping a known failure, which is sometimes the right call under time pressure but is a decision with an owner and a record, not a quiet omission.
- Adding a third-party component or embed, which brings its own accessibility — usually unverified, and inherited by you.
- Introducing a custom interactive control where a native element exists. Almost always the wrong trade, and always worth arguing for explicitly.
The framing that makes this easier to hold
The people affected mostly will not tell you. They will fail to complete the task and leave, and it will register as a conversion problem rather than an accessibility one.
So the only reliable signal is checking. That is why this rootnote is about verification rather than intent — an intention to be accessible produces almost nothing, and a keyboard pass before merge produces most of it.