Fix the focus trap in a modal dialog

Review the AI's codeEasy12 minMicrosoft and Apple style

Your task

An AI built a modal dialog that works well with a mouse. Keyboard users found that focus stayed on the page behind it, Tab wandered out of it, and Escape did nothing. Your team now writes the dialog's focus behavior down as a function and tests it.

An assistant wrote trap_modal_focus(focusable_ids, trigger_id, keys). It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • focusable_ids: the ids of the focusable elements inside the dialog, in Tab order. Two elements can share an id. They are still different elements.
  • trigger_id: the id of the element that opened the dialog.
  • keys: the keys pressed after the dialog opens: "Tab", "ShiftTab", "Escape" or any other key.
  • Return where focus is right after the dialog opens, then after each key. The list has one more entry than keys.

Rules the tests check:

  • On open, focus goes to the first position in focusable_ids. With no focusable elements, it goes to the dialog itself, written "dialog".
  • Tab moves focus to the next position in focusable_ids, and from the last position back to the first. ShiftTab moves to the previous position, and from the first to the last. So focus never leaves the dialog.
  • With no focusable elements, Tab and ShiftTab keep focus on "dialog".
  • Any other key leaves focus where it is.
  • Escape closes the dialog and returns focus to trigger_id. Once the dialog is closed, focus stays on trigger_id for every later key.

Examples

trap_modal_focus(focusable_ids: list[str], trigger_id: str, keys: list[str]) -> list[str]
Example 1
Inputtrap_modal_focus(["close", "save"], "openBtn", ["Tab", "Tab", "ShiftTab"])
Output["close", "save", "close", "save"]
Example 2
Inputtrap_modal_focus(["email", "submit", "close"], "trigger", ["Escape", "Tab"])
Output["email", "trigger", "trigger"]
Example 3
Inputtrap_modal_focus([], "openBtn", ["Tab", "Escape"])
Output["dialog", "dialog", "openBtn"]