diff --git a/packages/vuetify/src/components/VDialog/VDialog.tsx b/packages/vuetify/src/components/VDialog/VDialog.tsx index b4d5dc06b93..a347c6d0bd9 100644 --- a/packages/vuetify/src/components/VDialog/VDialog.tsx +++ b/packages/vuetify/src/components/VDialog/VDialog.tsx @@ -13,7 +13,7 @@ import { useProxiedModel } from '@/composables/proxiedModel' import { useScopeId } from '@/composables/scopeId' // Utilities -import { computed, mergeProps, nextTick, ref, watch } from 'vue' +import { mergeProps, nextTick, ref, watch } from 'vue' import { focusableChildren, genericComponent, IN_BROWSER, propsFactory, useRender } from '@/util' // Types @@ -89,24 +89,28 @@ export const VDialog = genericComponent()({ }, { immediate: true }) } + function onAfterEnter () { + if (overlay.value?.contentEl && !overlay.value.contentEl.contains(document.activeElement)) { + overlay.value.contentEl.focus({ preventScroll: true }) + } + } + watch(isActive, async val => { - await nextTick() - if (val) { - overlay.value!.contentEl?.focus({ preventScroll: true }) - } else { + if (!val) { + await nextTick() overlay.value!.activatorEl?.focus({ preventScroll: true }) } }) - const activatorProps = computed(() => - mergeProps({ + useRender(() => { + const overlayProps = VOverlay.filterProps(props) + const activatorProps = mergeProps({ 'aria-haspopup': 'dialog', 'aria-expanded': String(isActive.value), }, props.activatorProps) - ) - - useRender(() => { - const overlayProps = VOverlay.filterProps(props) + const contentProps = mergeProps({ + tabindex: -1, + }, props.contentProps) return ( ()({ { ...overlayProps } v-model={ isActive.value } aria-modal="true" - activatorProps={ activatorProps.value } + activatorProps={ activatorProps } + contentProps={ contentProps } role="dialog" + onAfterEnter={ onAfterEnter } { ...scopeId } > {{ diff --git a/packages/vuetify/src/components/VOverlay/VOverlay.tsx b/packages/vuetify/src/components/VOverlay/VOverlay.tsx index dd257f4aadb..d292df38e27 100644 --- a/packages/vuetify/src/components/VOverlay/VOverlay.tsx +++ b/packages/vuetify/src/components/VOverlay/VOverlay.tsx @@ -127,6 +127,7 @@ export const VOverlay = genericComponent()({ emits: { 'click:outside': (e: MouseEvent) => true, 'update:modelValue': (value: boolean) => true, + afterEnter: () => true, afterLeave: () => true, }, @@ -254,6 +255,10 @@ export const VOverlay = genericComponent()({ }) } + function onAfterEnter () { + emit('afterEnter') + } + function onAfterLeave () { _onAfterLeave() emit('afterLeave') @@ -309,6 +314,7 @@ export const VOverlay = genericComponent()({ persisted transition={ props.transition } target={ target.value } + onAfterEnter={ onAfterEnter } onAfterLeave={ onAfterLeave } >