Akryum / Akryum/floating-vue

Trigger event after tooltip/popover is made visible, for ex for .focus()

Offen
#661 3 Kommentare 1 Reaktion 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
TypeScript
Sterne
3.5k
Forks
341
Ø Merge
14 Min.
Gemergte PRs (30 T.)
8

Beschreibung

### Use case

We have create a popover menu component and would like to set the focus on the first element inside the popover right after it has appeared.

### Problem

To be able to call `.focus()` on the first element, we need to make sure that at this moment the Popover is mounted in the DOM **and** it has the class `.open` set, as it has to be actually visible.

This is currently not possible to detect reliably as there is no event triggered at the right moment.
In our current implementation we had used `$nextTick()` but since Popover uses `requestAnimationFrame`, there is no guarantee how many milliseconds must elapse before the `open` class gets set here: https://github.com/Akryum/v-tooltip/blob/master/src/components/Popover.vue#L360

To test the problem have a component listen to then `@open` event of the Popover, and use the following handler:
```
handleShow() {
console.log('Popover: handleShow className=', document.querySelector('.popover')?.className)
this.$nextTick(() => {
console.log('Popover after nextTick: handleShow className=', document.querySelector('.popover')?.className)
})
window.setTimeout(() => {
console.log('Popover after 1ms delay: handleShow className=', document.querySelector('.popover')?.className)
}, 1)
window.setTimeout(() => {
console.log('Popover after 5ms delay: handleShow className=', document.querySelector('.popover')?.className)
}, 5)
window.setTimeout(() => {
console.log('Popover after 20ms delay: handleShow className=', document.querySelector('.popover')?.className)
}, 20)
window.setTimeout(() => {
console.log('Popover after 50ms delay: handleShow className=', document.querySelector('.popover')?.className)
}, 50)
window.setTimeout(() => {
console.log('Popover after 100ms delay: handleShow className=', document.querySelector('.popover')?.className)
}, 100)
```

You can see my result here:
image

The messages in-between is where I tried to re-try the focus after a delay after noticing that the focus was not actually set.
As you can see the `$nextTick` did not get access to the DOM element and the "open" class only starts to appear after 50ms or so.

Note: this only happens the first time the popover opens. The second time it will directly set `this.isOpen=true` here https://github.com/Akryum/v-tooltip/blob/master/src/components/Popover.vue#L343

### Solution

Instead of having to add arbitrary delays, it would be nice to trigger the "show" event only once the popover is actually visible.
Or, if there are concerns with backwards compatibility, emit a new event "afterShow" there.

This way in our use case we could simply listen to that event and apply the focus there.

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.