Appointment holds and session timeouts can shut people out. For each limit, WCAG 2.2.1 needs one of three fixes: turn off, adjust, or extend after a warning.
A person using a screen reader, a switch or voice control often needs more time to read, fill in and submit a form. A person with a cognitive disability may need time to find a document. A fixed, silent timeout turns that into a failed task.
Success Criterion 2.2.1 applies to each time limit set by the content. At least one of these must be true:
Three exceptions apply: a limit required by a real-time event with no alternative, such as an auction; a limit that is essential, where extending would invalidate the activity; and limits longer than 20 hours. Only limits set by the content count, and server-side timeouts under the author's control are included.
These are the pages where a missed deadline has real cost: a lost slot, a rejected filing, a payment that did not go through. The extension must be reachable from the keyboard and announced to screen readers, not just shown as a visual countdown.
The simplest compliant pattern is a warning with a button that extends the hold. Here a hold lasts five minutes and the warning appears with one minute left, which is more than 20 seconds. It can be repeated.
setTimeout(releaseSlot, 5 * 60 * 1000); // silent releaseconst HOLD_MS = 5 * 60 * 1000, WARN_MS = 60 * 1000;
let warnTimer, releaseTimer;
function scheduleWarning() {
warnTimer = setTimeout(() => {
holdWarning.hidden = false; // role="alert" container
releaseTimer = setTimeout(releaseSlot, WARN_MS);
}, HOLD_MS - WARN_MS);
}
extendBtn.addEventListener("click", async () => {
clearTimeout(releaseTimer);
holdWarning.hidden = true;
await extendHold(); // server adds 5 more minutes
scheduleWarning(); // may be repeated
});
scheduleWarning();When the time limit comes from the application rather than from a security need, an option on the first screen is the strongest answer, because no warning is needed at all.
<p>You have 10 minutes to finish this enrollment form.</p><form action="/enroll/start" method="post">
<label>
<input type="checkbox" name="no_time_limit">
I need more time: remove the time limit for this application
</label>
<button type="submit">Start enrollment</button>
</form>An auto-dismissed toast is a time limit on reading. If it carries information the user needs, keep it on screen until it is dismissed or make the same information available elsewhere.
setTimeout(() => toast.remove(), 3000); // permit number gonetoast.innerHTML =
'Permit PRM-4471 filed. <button type="button" id="t-close">Dismiss</button>';
document.getElementById("t-close").addEventListener("click", () => toast.remove());
// Also shown on the application status page.A hold in a ticketing or booking app has the same problem. The warning must be exposed to VoiceOver and TalkBack, not only drawn.
SwiftUI:
.onReceive(timer) { _ in
if remaining <= 0 { releaseSlot() }
remaining -= 1
}.onReceive(timer) { _ in
remaining -= 1
if remaining == 60 { showExtend = true }
if remaining <= 0 { releaseSlot() }
}
.alert("Your reservation expires in 1 minute", isPresented: $showExtend) {
Button("Keep my spot") { extendHold(); remaining += 300 }
}Jetpack Compose:
LaunchedEffect(Unit) {
delay(5 * 60 * 1000L)
releaseSlot()
}var deadline by remember(holdId) {
mutableStateOf(System.currentTimeMillis() + 5 * 60 * 1000L)
}
// Keyed on deadline: extending moves it, which restarts this effect
LaunchedEffect(deadline) {
delay(deadline - 60 * 1000L - System.currentTimeMillis())
showExtend = true
delay(60 * 1000L)
releaseSlot()
}
if (showExtend) {
AlertDialog(
onDismissRequest = {},
title = { Text("Your reservation expires in 1 minute") },
confirmButton = {
TextButton(onClick = {
extendHold(); deadline += 5 * 60 * 1000L; showExtend = false
}) {
Text("Keep my spot")
}
}
)
}setTimeout, setInterval, meta http-equiv="refresh", session lifetime settings and slot-hold logic.Common mistakes: a warning shown for 10 seconds, an extend button that works only once, a visual countdown with no announcement, and calling a limit "security" without checking whether it can be extended safely. Security limits can be essential, but that has to be true, not assumed.
Agencies often inherit timeouts from the vendor platform and assume they cannot be changed. Ask the vendor for configurable limits before accepting that.
Ship it when:
Related reading: vendors and third-party content.