Skip to content

[Bug Report][3.3.20] VDialog focus trap is broken by display: none inputs #18400

@shengslogar

Description

@shengslogar

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.

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.

Metadata

Metadata

Assignees

Labels

C: VDialogT: bugFunctionality that does not work as intended/expected

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions