-
-
Notifications
You must be signed in to change notification settings - Fork 7.1k
Description
Environment
Vuetify Version: 3.3.20
Vue Version: 3.3.4
Browsers: Chrome 117.0.0.0
OS: Mac OS 10.15.7
Steps to reproduce
Place any focusable element, as determined by the following code block (<input>
, <a href>
, etc.) with style="display: none"
inside a VDialog
.
vuetify/packages/vuetify/src/util/helpers.ts
Lines 646 to 651 in 2dee949
export function focusableChildren (el: Element, filterByTabIndex = true) { | |
const targets = ['button', '[href]', 'input:not([type="hidden"])', 'select', 'textarea', '[tabindex]'] | |
.map(s => `${s}${filterByTabIndex ? ':not([tabindex="-1"])' : ''}:not([disabled])`) | |
.join(', ') | |
return [...el.querySelectorAll(targets)] as HTMLElement[] | |
} |
Expected Behavior
VDialog
's focus trap should ignore visually hidden inputs.
Actual Behavior
Focus escapes VDialog
and onto background elements.
Reproduction Link
https://play.vuetifyjs.com/#...
Other comments
While I personally don't tend to hide elements by way of display: none
, I ran into this issue when trying to embed a TinyMCE component into a dialog. Their WYSIWYG uses a hidden textarea
.
I opened a similar issue (#15745) in v2. The resolution addressed this problem for negative tab indices and <input type="hidden">
.
While another selector change could fix this single use case (for inline styles; we'd have to expensively calculate element dimensions otherwise), this approach might be revised to be more robust. For example, Headless UI targets a few extra selectors (including contenteditable
), but also appears to check if document.activeElement
is set to the element that we just tried to focus. If not, it moves on to the next one. This seems like it might provide a future catch-all to unfocusable edge cases.