Focus management problems (active element is removed before redirecting focus) - hacky fixes and theories
Instructions: using a screen reader, navigate to the button in each example and activate it. It will be replaced with a message. Is that message announced when it is focused?
Example 1: theory: change the DOM enough so that the browser doesn't recover to the element that is getting focus
Example 2: set focus after element loads
Example 3: force reset focus (send to sr-only div and then back)
Example 4: force reset focus (send to sr-only div and then back) - after a slight delay
Example 5: visually hide the trigger, then send focus to the new content, then remove the trigger
results
NVDA 2020.1 + Chrome 84:
example 1: pass (loading section)
example 2: fail (silence)
example 3: fail (silence)
example 4: pass (please wait, loading)
example 5: fail (silence)
NVDA 2020.1 + Firefox 78:
example 1: pass (loading)
example 2: fail (text frame)
example 3: fail (text frame)
example 4: pass (please wait, loading)
example 5: fail (silence)
JAWS 2020 + Chrome 84:
example 1: fail (load, heading level 2)
example 2: pass (h1 was announced, loading)
example 3: pass (loading)
example 4: pass (please wait, loading)
example 5: pass (loading)
JAWS 2020 + Firefox 78:
example 1: pass (loading)
example 2: pass (h1 was announced, loading)
example 3: pass (loading)
example 4: pass (please wait, frame, loading)
example 4: pass (loading)
VO MacOS 10.15.6 + Safari 13.1.1:
example 1: pass (loading, group)
example 2: pass (loading, group)
example 3: pass (loading, group)
example 4: pass (loading, group)
example 5: pass (loading, group)
VO iOS 13.6 + Safari:
example 1: pass (loading)
example 2: pass (theories, loading)
example 3: pass (loading)
example 4: pass (loading)
example 5: pass (loading)
Conclusions
Example 4 was the only one that consistently passed.
It seems that the the delay is needed so that everything in the a11y stack has a chance to catch up and notice what is changing.
The fact that a delay is needed makes this fragile. How much of a delay is needed? Do we need a longer delay on slower machines?
In theory, it could be possible to make example 4 a function. For example when you call focusWithDelay('#target', callback), the function could inject the 'please wait' sr-only div, send focus to it, perform the callback (remove and replace content), then send focus to the desired selector, then remove the 'please wait' sr-only div, all while handling appropriate delays.