Skip to content

Commit

Permalink
feat(VOverlay): add closeOnBack prop
Browse files Browse the repository at this point in the history
fixes #15130
  • Loading branch information
KaelWD committed May 22, 2022
1 parent 44fb381 commit 883ba1a
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 15 deletions.
1 change: 1 addition & 0 deletions packages/api-generator/src/locale/en/v-overlay.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"props": {
"absolute": "Applies **position: absolute** to the content element.",
"closeOnBack": "Closes the overlay content when the browser's back button is pressed or `$router.back()` is called, cancelling the original navigation. `persistent` overlays will cancel navigation and animate as if they were clicked outside instead of closing.",
"contained": "Limits the size of the component and scrim to its offset parent. Implies `absolute` and `attach`.",
"opacity": "Sets the overlay opacity",
"zIndex": "The z-index used for the component"
Expand Down
26 changes: 17 additions & 9 deletions packages/vuetify/src/components/VOverlay/VOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { makePositionStrategyProps, usePositionStrategies } from './positionStra
import { makeScrollStrategyProps, useScrollStrategies } from './scrollStrategies'
import { makeThemeProps, provideTheme } from '@/composables/theme'
import { makeTransitionProps, MaybeTransition } from '@/composables/transition'
import { useBackButton } from '@/composables/router'
import { useBackButton, useRouter } from '@/composables/router'
import { useToggleScope } from '@/composables/toggleScope'
import { useBackgroundColor } from '@/composables/color'
import { useProxiedModel } from '@/composables/proxiedModel'
import { useRtl } from '@/composables/rtl'
Expand Down Expand Up @@ -83,6 +84,10 @@ export const VOverlay = genericComponent<new () => {
props: {
absolute: Boolean,
attach: [Boolean, String, Object] as PropType<boolean | string | Element>,
closeOnBack: {
type: Boolean,
default: true,
},
contained: Boolean,
contentClass: null,
noClickAnimation: Boolean,
Expand Down Expand Up @@ -163,14 +168,17 @@ export const VOverlay = genericComponent<new () => {
}
}

useBackButton(next => {
if (isTop.value && isActive.value) {
next(false)
if (!props.persistent) isActive.value = false
else animateClick()
} else {
next()
}
const router = useRouter()
useToggleScope(() => props.closeOnBack, () => {
useBackButton(router, next => {
if (isTop.value && isActive.value) {
next(false)
if (!props.persistent) isActive.value = false
else animateClick()
} else {
next()
}
})
})

const top = ref<number>()
Expand Down
1 change: 1 addition & 0 deletions packages/vuetify/src/components/VTooltip/VTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export const VTooltip = genericComponent<new () => {
persistent
open-on-click={ false }
open-on-hover
close-on-back={ false }
role="tooltip"
eager
activatorProps={{
Expand Down
11 changes: 5 additions & 6 deletions packages/vuetify/src/composables/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import { getCurrentInstance, propsFactory } from '@/util'
import {
computed,
onBeforeUnmount,
onMounted,
nextTick,
onScopeDispose,
resolveDynamicComponent,
toRef,
} from 'vue'
Expand Down Expand Up @@ -74,13 +74,12 @@ export const makeRouterProps = propsFactory({
}, 'router')

let inTransition = false
export function useBackButton (cb: (next: NavigationGuardNext) => void) {
const router = useRouter()
export function useBackButton (router: Router | undefined, cb: (next: NavigationGuardNext) => void) {
let popped = false
let removeBefore: (() => void) | undefined
let removeAfter: (() => void) | undefined

onMounted(() => {
nextTick(() => {
window.addEventListener('popstate', onPopstate)
removeBefore = router?.beforeEach((to, from, next) => {
if (!inTransition) {
Expand All @@ -94,7 +93,7 @@ export function useBackButton (cb: (next: NavigationGuardNext) => void) {
inTransition = false
})
})
onBeforeUnmount(() => {
onScopeDispose(() => {
window.removeEventListener('popstate', onPopstate)
removeBefore?.()
removeAfter?.()
Expand Down
15 changes: 15 additions & 0 deletions packages/vuetify/src/composables/toggleScope.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { effectScope, watch } from 'vue'
import type { EffectScope, WatchSource } from 'vue'

export function useToggleScope (source: WatchSource<boolean>, cb: () => void) {
let scope: EffectScope | undefined
watch(source, active => {
if (active && !scope) {
scope = effectScope()
scope.run(cb)
} else {
scope?.stop()
scope = undefined
}
}, { immediate: true })
}

0 comments on commit 883ba1a

Please sign in to comment.