Prompt and context
Search, save, and upload complete without navigation or moving focus. Visual users see “Saving”, “Saved”, or “Save failed”, while the update may happen outside the focused control. The goal is a short, actionable announcement that does not interrupt input, with keyboard, no-script, and network-failure fallbacks.
What the interviewer tests
The answer should distinguish advisory status, errors, and urgent alerts; establish a live region before updates; control duplicate announcements, race conditions, and focus movement; and include server results, retry actions, and testing rather than adding one aria-live attribute.
Questions to clarify
- Which updates are advisory, and which block the next action?
- Can users trigger concurrent requests, and do responses carry sequence numbers?
- Does failure have an inline retry, undo, or details action?
- Should focus stay in the editor after success, and where should it go for an error?
- Are ordinary form submission, keyboard use, zoom, and forced colors required?
30-second answer
I would render an empty role="status" region in the initial DOM and write ordinary progress and completion messages into it. Its polite behavior should not steal focus. Actionable errors get visible text and a recovery path near the control; only truly urgent events use an alert. I would deduplicate and throttle announcements, reject stale responses by sequence number, and test keyboard, screen reader, network failure, and concurrent requests.
Step-by-step deep answer
Step 1: Model state explicitly
Keep idle, pending, success, error, and cancelled separate. The status region says the current outcome, such as “Saving”, “Saved”, or “Save failed; retry”, rather than internal request names or every percentage. Store field errors, retry actions, and control associations separately.
Step 2: Create the live region first
W3C and MDN recommend creating the live region before changing its content. role="status" is suitable for advisory information and has an implicit aria-live="polite"; do not add the attribute only when an update occurs.
<p id="save-status" role="status" aria-atomic="true"></p>
<button type="submit">Save</button>Step 3: Control announcement cadence
Do not write identical text repeatedly or announce every keystroke during search. Debounce high-frequency results and announce a meaningful summary such as “Results updated”. Completion, failure, and required action should name the next step. aria-live="assertive" interrupts speech and should be rare.
Step 4: Handle races and cancellation
Give each request an increasing sequence or an AbortController. Only the newest response from a mounted component may update the status. A cancelled request is not a failure announcement; a new request replaces the previous pending message.
Step 5: Coordinate focus and errors
Do not move focus for ordinary success; let the user continue. For failure, render visible text and associate it with the control using aria-describedby; page-level failures need a focusable summary and retry button. Choose one primary channel so a focus jump and live announcement do not duplicate each other.
Step 6: Preserve a fallback path
The server should still accept ordinary form submission and return structured results. On JavaScript failure, timeout, or expired permission, text should state the status and action, such as “Save failed; try again”, rather than leaving a spinner. Do not clear the user’s input.
Trade-offs and boundaries
status, alert, and visible errors
status is for polite notification; alert interrupts and should not replace every error. Visible errors remain necessary because speech is not the only channel. Color, icons, and animation supplement text.
Progress detail versus noise
Show upload percentages visually, but announce only start, meaningful phases, and completion. Updating a live region every one percent creates noise; calibrate throttling with real devices and users.
Rollout plan and evidence
Component and API contract
Centralize message text, deduplication, and sequence checks in one status component. The API returns structured success, retryable, and fieldErrors fields; the component maps them to user language instead of exposing server codes.
Verification matrix
Complete search, save, and upload by keyboard and confirm one announcement in NVDA and VoiceOver. Cover slow networks, timeouts, double clicks, out-of-order responses, cancellation, unload, forced colors, and 200% zoom. Automate DOM semantics, then manually verify spoken order.
Common mistakes and follow-ups
Mistake: adding aria-live dynamically
Keep the node and attribute present, then update its text; otherwise some assistive technologies can miss the first change.
Mistake: moving focus to success text
That interrupts editing. Keep focus unless the user must address an error or inspect a result.
Mistake: making every error assertive
High-priority speech interrupts reading. Reserve it for genuinely urgent attention and provide visible recovery.
Follow-up: preventing stale responses
Compare a monotonic sequence, or combine cancellation with a sequence check; cancellation alone does not prove a callback cannot run.
Follow-up: proving effectiveness
Bring screen-reader observations, keyboard flows, network failures, and race-condition evidence rather than only an automated scan result.