Phase 3 · Browser DevelopmentModule 24~38 min read

Accessible UI Architecture

Design resilient interfaces that work with keyboards, assistive technology, and varied devices.

What you'll learn

Accessible interfaces begin with semantic HTML and a state model that keeps visuals, focus, keyboard behavior, and assistive-technology announcements synchronized.

By the end of this lesson, you'll be able to:

  • Choose native semantics before ARIA
  • Manage focus after state changes
  • Build state-driven keyboard interactions

Core mental model

Use this decision table as a compact reference. Focus on what each tool means and when it earns its place in production code.

ConceptWhat it meansDecision rule
Native semanticsBuilt-in role, keyboard behavior, and form integrationChoose the correct element before adding ARIA
Focus managementProgrammatic focus follows meaningful context changesMove focus only when users would otherwise be lost
ARIA stateAccessibility metadata mirrors UI stateUpdate from the same source of truth as visuals

Professional workflow

Build the behavior in small, observable steps. Each step should leave something you can inspect or test.

  1. Describe the accessible interaction boundary: inputs, outputs, state, timing, and expected failures.
  2. Implement the smallest correct path with names that expose intent.
  3. Add edge cases and failure handling before introducing abstractions.
  4. Verify behavior with realistic data and one deliberately adversarial example.
  5. Refactor only after the observable behavior is protected.

Make behavior observable

Before optimizing or abstracting, make inputs, outputs, state changes, timing, and failure paths visible. JavaScript becomes much easier to reason about when hidden work is exposed.

Guided code lab

Synchronize a disclosure

A native button controls one region and exposes the same open state.

disclosure.js
const button = document.querySelector("#topics-button");
const panel = document.querySelector("#topics-panel");
button.addEventListener("click", () => {
  const open = button.getAttribute("aria-expanded") === "true";
  button.setAttribute("aria-expanded", String(!open));
  panel.hidden = open;
});

Focus after adding content

A newly displayed error summary becomes the next meaningful reading position.

error-focus.js
function showErrors(messages) {
  const summary = document.querySelector("#errors");
  summary.replaceChildren(...messages.map(message => {
    const item = document.createElement("p");
    item.textContent = message;
    return item;
  }));
  summary.hidden = false;
  summary.focus();
}

Production practice

Contract

Keep the accessible interaction API explicit: accepted state, emitted events, DOM ownership, and cleanup.

Verification

Test with keyboard input, missing elements, repeated initialization, and teardown—not only a mouse happy path.

Operations

Measure user-visible latency and remove listeners, observers, object URLs, or media tracks when the feature ends.

Common failure mode

Adding role=button to a div does not add keyboard activation, focusability, disabled behavior, or form semantics.

Independent workshop

Build an accessible modal dialog and document its focus lifecycle.

Your finished workshop must include:

  • Native open/close controls
  • Initial, trapped, and restored focus
  • Escape handling and a meaningful label

Definition of done

Demonstrate the happy path and at least two edge cases, keep responsibilities separated, and add a short note explaining one design choice.

Recap & quick check

Key takeaways

  • Native semantics carry behavior
  • ARIA reflects—not creates—interaction
  • Focus follows meaningful context
  • One state source drives every representation

Quick check

1. What is the first rule of ARIA?

2. What should aria-expanded mirror?

3. Where should focus return after a dialog closes?

Keep the workshop. Later modules deliberately build on these decisions, so each exercise can become part of your final portfolio architecture.