• Success Criterion 2.1.2
  • Conformance level A

Widget Where Tab Cycles Internally With No Way Out

2.1.2 — No Keyboard Trap

Scenario

Setting

A customer-support live-chat widget

What’s wrong

Focus loops inside a widget (calendar, editor, embedded iframe) where Tab cycles internally forever.

Example

<div class="chat-widget">
  <div class="mini-calendar">
    <!-- 42 day cells, each tabindex="0"; the last cell's Tab wraps back to the first -->
  </div>
  <textarea class="chat-input"></textarea>
</div>

Why it matters

A customer tabbing through the calendar to pick an appointment date can never reach the chat input below it, so they can't ask a follow-up question.

How to test

Tab repeatedly inside a widget (calendar, rich editor, embedded iframe): if Tab cycles internally forever with no way to exit to the rest of the page, it fails.

How to fix

A widget's internal Tab loop should only cover its own controls; let the natural document order carry Tab onward once the last one is reached.

lastDayCell.addEventListener('keydown', (e) => {
  if (e.key === 'Tab' && !e.shiftKey) {
    e.preventDefault();
    chatInput.focus();
  }
});

Outcome

A customer moves through the calendar with Tab and lands right on the chat input to type their question.

Who is affected

Keyboard-only users get stuck cycling day cells and can't reach the rest of the widget.

Learn more