Releases: renatodeleao/a11y-vue-dialog
v0.5.1
Fixes focus-trap
initialFocus
option handling of autofocus
elements. Here's the default focus order:
1. focusRef` binding
2. elements with `[autofocus]` attribute — (`document.querySelector('[autofocus]'))
3. first focusable element
4. use focus-trap fallback (dialogRef)
The problem was that we weren't checking if 2 was a valid candidate for the autofocus
attribute — input, select, button and textarea to be precise — and I faced a bug where a vue
input component wrapper didn't have inheritAttrs: false
, so a magic <div autofocus>
was trying to be erroneously focused, not focusing the actual input.
Note that if you want to focus an invalid element you can still do
<div tabindex="0" v-bind="focusRef.attrs">
If you're that kind of person, don't forget the tabindex!
</div>
v0.5.0
Focus management like a pro!
v0.4.9
- Fix incorrect usage of
package.json
main
field, that would break systems without specific setup for transpilling our source code... i mean why the heck was i shipping a package point to the src in the first place? - Updates rollup config accordingly
- adds
upkg
field that points to minified version - Bump dependecies
Thanks to Dependabot, you're tha bot!
And this kids, is why you shouldn't do OSS after 10hours of work
It's the same as the previous release, but with actual build
or dist
code in it.
focus-visible breaking focusTrap 🚨
🚨🚨🚨 This release was published without the build code, use the next patch.🚨🚨🚨
Another day, another exception.
On a project of mine i've added focus-visible
polyfill as to match a ui requirement on focus styles and suddenly the dialog was broken. focus-visible
polyfill adds attributes to elements and attaches focus and blur events to the document: those attribute changes were triggering mutations, and the events were setting document.activeElement
to body for a brief moment. Our mutationObserver
was catching that brief moment as "the focused item was removed/hidden and it's not focus anymore, do the focus trap magic to find the next focusable element" But the next focusable element to body
is always the first focusable element of the dialog, so we're stuck in a loop.
Fix was just moving our observer verifications into a setTimeout()
call, moving them to the next queue, after the focus-visible
and other focus attaching plugins/polyfills done their things
FOCUS FOCUS FOCUS 2.0
Make the naive patch on v0.4.5
not so naive, by keeping track of mutated focus elements positions and continue the expected tab sequence even after focus is lost to body
(out of the trap) due to a mutation event (could be v-if
, v-show
, class
that hidden, setting the button disabled
— basically anything that makes an interactive/focusable element inert
).
This is the TL;DR and bfade5b description and comments might help with details if interested.
I've spent more time on this than i should, got a couple of grey hairs and I imagine that there's probably a better/faster/stronger/simpler way of doing it. At this point I just don't fucking care. I've reached the breaking point and managed to get out of there and that's all that matters to me.
Yes it still doesn't work as expected for all possible scenarios, but it doesn't break either. I'll bump this to a minor as soon as i've got a definitive solution, but I don't want to hear about dialogs in the next month, just want to go back to my job now. Check #22 for progress.
☮️
v-if or v-show (or css similars) within dialog and focus management
This release patches a bug that happened when focused element was removed/hidden from the dom after an action on itself. #21
Note: this is not a perfect solution, but at least we can close the dialog 🤷♂️ afterwards.
I'll release a more robust solution on next patch.
Edge case on pseudo-drag closing
A user found this edge case while "pseudo-dragging2 text selection from within to outside dialog (backdrop). Since its dialog backdrop was allso the root (wrapper) of the dialogRef
itself, mouseup
event bubbled
and triggered click
event at backdropRef
(note: expected native behaviour) and closing the dialog.
Although it's the native behaviour, it's apparently not user-friend.
I wasn't sure if i should write code to handle this edge case or add a note to the docs, saying:
if you don't want this behaviour, make sure your
backdropRef
is not the same element as your dialog wrapper (root).
I end up including it, till some-else complains, hopefully after v1.0.0 will have more feedback for the expected usage.
Uff, this was long: now this doesn't happen by default ⬇
Implementation
remove opinionated scroll preventing behavior
adding overflow hidden to this.$root was assuming too much of it's html markup structure and could create unwanted side effects (like empty scrollbars on non-full-width root divs).
This was added to prevent modal jump, but adding overflow-y: scroll
to html is way more common now.
Anyways, if you need that kind of control, add watcher
the open
prop of your composition, and perform your custom side-effects there.
Focus focus focus
- More closely aligned with WAI ARIA guidelines on focus: now it gives priority to autofocus elements instead of just focusing on the first focusable element (fallback)
- Adds focusRef to delegate consumer what's the appropriate element to focus for each dialog scenario
- Improves and fixes focusTrap error.
- Adds specs for the features and band-aids failing ones
- Tapping
esc
while on focused on an<input type="search">
will not close the dialog unless the input is empty (default behaviour of this input is to reset the input value and we don't want to interfere with that) - Fixes a bug where selecting text content within the dialog would remove the possibility of closing the dialog using keyboard