Problem
PR #4980 added a focus trap to `HostSelectionDialog.vue` at line ~417 using a `focusin` listener that snaps focus to `focusable[0]` whenever focus escapes.
This breaks natural keyboard navigation:
- Shift+Tab on the first focusable element → lands on `body` → listener snaps back to first → user can never wrap to last
- Any click outside the dialog on a focusable element → bounces focus back to first control → disorients users and blocks browser devtools usage
Fix
Implement a real focus trap via keydown listener on the dialog root that intercepts Tab/Shift+Tab and wraps focus:
- Tab on last focusable → focus first
- Shift+Tab on first focusable → focus last
- All other tabs: default browser behavior
BaseModal has the same pattern — fix both together.
Related discoveries
- `_uid = Math.random().toString(36).substr(2, 9)` — `substr` is deprecated. BaseModal does the same. Use Vue 3.5+ `useId()`.
Meta
Found during session 144 quality gate (2026-04-17).
Problem
PR #4980 added a focus trap to `HostSelectionDialog.vue` at line ~417 using a `focusin` listener that snaps focus to `focusable[0]` whenever focus escapes.
This breaks natural keyboard navigation:
Fix
Implement a real focus trap via keydown listener on the dialog root that intercepts Tab/Shift+Tab and wraps focus:
BaseModal has the same pattern — fix both together.
Related discoveries
Meta
Found during session 144 quality gate (2026-04-17).