Skip to content

Conversation

memorandumtk
Copy link
Contributor

Description

  • Registers a keydown event listener on VDialog to focus on the first focusable element when the Tab key is pressed on the last focusable element in the dialog.
  • Added two tests to test focus behavior when focus moves from the first and last buttons in a VDialog.

fixes #21945

Markup:

<template>
  <div class="text-center pa-4">
    <v-dialog v-model="dialog" max-width="400">
      <template v-slot:activator="{ props: activatorProps }">
        <v-btn v-bind="activatorProps"> Open Dialog </v-btn>
      </template>

      <v-btn @click="dialog = false"> Disagree </v-btn>
      <v-btn @click="dialog = false"> Agree </v-btn>
    </v-dialog>
  </div>
</template>

<script setup>
  import { ref } from 'vue'

  const dialog = ref(false)

  // for debugging
  const showPressedKey = (e) => {
    const now = new Date()
    const msg = `[${now.toISOString()}] pressed: ${e.key}${e.shiftKey ? ' with shift key' : ''}`
    console.log(msg)
  }

  window.addEventListener('keydown', showPressedKey)
</script>

@J-Sek J-Sek added T: bug Functionality that does not work as intended/expected C: VDialog labels Sep 22, 2025

onBeforeUnmount(() => {
document.removeEventListener('focusin', onFocusin)
document.removeEventListener('keydown', onKeydown)
Copy link
Contributor

@J-Sek J-Sek Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new handler replaces onFocusin. Is there any reason left to keep both? Yes, to capture the first focus.

Lines 69-79 could be replaced with focusable[0]?.focus() like in VMenu.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see.
I edited it according to the comment before editing, so I'll correct it again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have two questions.

  1. Did you mean that the first focus was on the dialog itself (v-overlay__content)? I assumed it was on the first focusable element in the dialog (the "Disagree" button in the video below), so I just wanted to confirm.

  2. I was checking the focus behavior of VMenu and noticed that when you press tab on Vmenu, the behavior is correct the first time you press tab, but the second time, Vmenu seems to close. Should I fix this?

demo in play.vuetify

screen-capture.24.webm

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. VMenu and VDialog, both try to "capture" the focus when an interaction occurs and the focus is set outside. I don't know the origin of this implementation, but it feels slightly better than auto-focus within (done by native <dialog>) as it would be reasonable to load the dialog content progressively, show spinner, load stuff.

That said, the code between those is not the same because VDialog applied (bugged) focus trap. My suggestion would be to have keydown handler focus on the trap, while focusin handler can do the same thing as VMenu, so as a result, the code should look the same. No need to refactor/abstract a new composable. It is going to happen eventually (#22106). For now, we should just avoid 2 pieces of code having the same responsibility.

  1. Better to keep the PR focused on one thing. It might feel a bit annoying that user tab-out of the menu and is supposed to use up/down arrows for a VList within.. Nobody rised this issue until now, so I guess it is not a bug. It might be equally annoying to be stuck within a menu/popover because developer forgot to put :retain-focus="false", right? Either way, 3.11.0 will hopefully give us an option to set focus trap VMenu and VNavigationDrawer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your explanation and sharing the current refactor PR 22106!
I've pushed a fix that brings the code as close as possible to Vmenu onFocus. I'd appreciate it if you could review it.

@J-Sek J-Sek changed the title fix(VDialog): fix focus behavior when tab key is pressed fix(VDialog): fix focus trap when tabbing forward Sep 28, 2025
@J-Sek J-Sek merged commit 50a150b into vuetifyjs:master Sep 28, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C: VDialog T: bug Functionality that does not work as intended/expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug Report][3.9.5] vDialog focus trap is working only for Shift-Tab

3 participants