You've already forked AstralRinth
fix(app): notifications appearing with modal open (#6348)
fix: notifications appearing with modal open
This commit is contained in:
@@ -136,7 +136,6 @@
|
||||
import { XIcon } from '@modrinth/assets'
|
||||
import { computed, nextTick, onUnmounted, ref } from 'vue'
|
||||
|
||||
import { useDebugLogger } from '../../composables/debug-logger'
|
||||
import { useVIntl } from '../../composables/i18n'
|
||||
import { useModalStack } from '../../composables/modal-stack'
|
||||
import { useScrollIndicator } from '../../composables/scroll-indicator'
|
||||
@@ -145,7 +144,6 @@ import { commonMessages } from '../../utils/common-messages'
|
||||
import ButtonStyled from '../base/ButtonStyled.vue'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
const debug = useDebugLogger('NewModal')
|
||||
|
||||
const modalBehavior = injectModalBehavior(null)
|
||||
const {
|
||||
@@ -235,138 +233,56 @@ function getFocusableElements(): HTMLElement[] {
|
||||
}
|
||||
|
||||
function show(event?: MouseEvent) {
|
||||
debug('show: start', {
|
||||
header: props.header,
|
||||
open: open.value,
|
||||
visible: visible.value,
|
||||
stackSize: modalStackSize(),
|
||||
hasEvent: !!event,
|
||||
})
|
||||
props.onShow?.()
|
||||
debug('show: after onShow', { header: props.header })
|
||||
const wasEmpty = modalStackSize() === 0
|
||||
stackDepth.value = modalStackSize()
|
||||
debug('show: before open=true', {
|
||||
header: props.header,
|
||||
wasEmpty,
|
||||
stackDepth: stackDepth.value,
|
||||
})
|
||||
open.value = true
|
||||
debug('show: after open=true', {
|
||||
header: props.header,
|
||||
open: open.value,
|
||||
modalBodyExists: !!modalBodyRef.value,
|
||||
})
|
||||
previousFocusEl = document.activeElement
|
||||
debug('show: previous focus captured', {
|
||||
header: props.header,
|
||||
previousFocusTag: previousFocusEl instanceof HTMLElement ? previousFocusEl.tagName : null,
|
||||
previousFocusClass: previousFocusEl instanceof HTMLElement ? previousFocusEl.className : null,
|
||||
})
|
||||
pushModal()
|
||||
debug('show: after pushModal', { header: props.header, stackSize: modalStackSize() })
|
||||
if (wasEmpty) modalBehavior?.onShow?.()
|
||||
debug('show: after modalBehavior onShow', { header: props.header })
|
||||
|
||||
document.body.style.overflow = 'hidden'
|
||||
window.addEventListener('keydown', handleWindowKeyDown)
|
||||
window.addEventListener('mousedown', updateMousePosition)
|
||||
debug('show: listeners attached', { header: props.header })
|
||||
if (event) {
|
||||
updateMousePosition(event)
|
||||
} else {
|
||||
mouseX.value = Math.round(window.innerWidth / 2)
|
||||
mouseY.value = Math.round(window.innerHeight / 2)
|
||||
}
|
||||
debug('show: mouse position set', {
|
||||
header: props.header,
|
||||
mouseX: mouseX.value,
|
||||
mouseY: mouseY.value,
|
||||
})
|
||||
setTimeout(() => {
|
||||
debug('show: timeout before visible=true', {
|
||||
header: props.header,
|
||||
open: open.value,
|
||||
visible: visible.value,
|
||||
modalBodyExists: !!modalBodyRef.value,
|
||||
})
|
||||
visible.value = true
|
||||
debug('show: timeout after visible=true', {
|
||||
header: props.header,
|
||||
open: open.value,
|
||||
visible: visible.value,
|
||||
modalBodyExists: !!modalBodyRef.value,
|
||||
})
|
||||
nextTick(() => {
|
||||
debug('show: nextTick focus start', {
|
||||
header: props.header,
|
||||
modalBodyExists: !!modalBodyRef.value,
|
||||
})
|
||||
const focusable = getFocusableElements()
|
||||
debug('show: focusable elements', {
|
||||
header: props.header,
|
||||
count: focusable.length,
|
||||
firstTag: focusable[0]?.tagName,
|
||||
})
|
||||
if (focusable.length > 0) {
|
||||
focusable[0].focus()
|
||||
} else {
|
||||
modalBodyRef.value?.focus()
|
||||
}
|
||||
debug('show: nextTick focus done', { header: props.header })
|
||||
})
|
||||
}, 50)
|
||||
debug('show: end', { header: props.header })
|
||||
}
|
||||
|
||||
function hide() {
|
||||
debug('hide: start', {
|
||||
header: props.header,
|
||||
open: open.value,
|
||||
visible: visible.value,
|
||||
disableClose: props.disableClose,
|
||||
stackSize: modalStackSize(),
|
||||
})
|
||||
if (props.disableClose) {
|
||||
debug('hide: ignored disableClose', { header: props.header })
|
||||
return
|
||||
}
|
||||
props.onHide?.()
|
||||
debug('hide: after onHide', { header: props.header })
|
||||
visible.value = false
|
||||
debug('hide: after visible=false', { header: props.header, visible: visible.value })
|
||||
popModal()
|
||||
debug('hide: after popModal', { header: props.header, stackSize: modalStackSize() })
|
||||
if (modalStackSize() === 0) {
|
||||
modalBehavior?.onHide?.()
|
||||
document.body.style.overflow = ''
|
||||
}
|
||||
window.removeEventListener('keydown', handleWindowKeyDown)
|
||||
window.removeEventListener('mousedown', updateMousePosition)
|
||||
debug('hide: listeners removed', { header: props.header })
|
||||
if (previousFocusEl instanceof HTMLElement) {
|
||||
debug('hide: restoring focus', {
|
||||
header: props.header,
|
||||
previousFocusTag: previousFocusEl.tagName,
|
||||
previousFocusClass: previousFocusEl.className,
|
||||
})
|
||||
previousFocusEl.focus()
|
||||
}
|
||||
previousFocusEl = null
|
||||
setTimeout(() => {
|
||||
debug('hide: timeout before open=false', {
|
||||
header: props.header,
|
||||
open: open.value,
|
||||
visible: visible.value,
|
||||
})
|
||||
open.value = false
|
||||
debug('hide: timeout after open=false', {
|
||||
header: props.header,
|
||||
open: open.value,
|
||||
visible: visible.value,
|
||||
})
|
||||
}, 300)
|
||||
debug('hide: end', { header: props.header })
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
@@ -394,12 +310,6 @@ function updateMousePosition(event: { clientX: number; clientY: number }) {
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
debug('unmounted', {
|
||||
header: props.header,
|
||||
open: open.value,
|
||||
visible: visible.value,
|
||||
stackSize: modalStackSize(),
|
||||
})
|
||||
if (open.value) {
|
||||
popModal()
|
||||
window.removeEventListener('keydown', handleWindowKeyDown)
|
||||
@@ -528,11 +438,12 @@ defineOptions({
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
transform: translate(v-bind(mouseXOffset), v-bind(mouseYOffset));
|
||||
transition: all 0.2s ease-out;
|
||||
transition: none;
|
||||
|
||||
&.shown {
|
||||
visibility: visible;
|
||||
transform: translate(0, 0);
|
||||
transition: all 0.2s ease-out;
|
||||
|
||||
> .modal-body {
|
||||
opacity: 1;
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
class="popup-notification-group"
|
||||
:class="{
|
||||
'has-sidebar': hasSidebar,
|
||||
'has-modal': hasModalActive,
|
||||
}"
|
||||
:style="notificationGroupStyle"
|
||||
>
|
||||
<transition-group name="popup-notifs">
|
||||
<div
|
||||
@@ -155,6 +157,7 @@ import {
|
||||
} from '@modrinth/assets'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useModalStack } from '../../composables/modal-stack'
|
||||
import {
|
||||
injectPopupNotificationManager,
|
||||
type PopupNotification,
|
||||
@@ -169,6 +172,11 @@ const popupNotificationManager = injectPopupNotificationManager()
|
||||
const notifications = computed<PopupNotification[]>(() =>
|
||||
popupNotificationManager.getNotifications(),
|
||||
)
|
||||
const { stackCount } = useModalStack()
|
||||
const hasModalActive = computed(() => stackCount.value > 0)
|
||||
const notificationGroupStyle = computed(() => ({
|
||||
zIndex: hasModalActive.value ? 100 + stackCount.value * 10 + 8 : 200,
|
||||
}))
|
||||
|
||||
const stopTimer = (n: PopupNotification) => popupNotificationManager.stopNotificationTimer(n)
|
||||
const setNotificationTimer = (n: PopupNotification) =>
|
||||
@@ -252,12 +260,21 @@ withDefaults(
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
transition:
|
||||
opacity 0.2s ease-in-out,
|
||||
transform 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.popup-notification-group.has-sidebar {
|
||||
right: calc(var(--right-bar-width, 0px) + 1.5rem);
|
||||
}
|
||||
|
||||
.popup-notification-group.has-modal {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transform: translateY(-0.5rem);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
.popup-notification-group {
|
||||
right: 0.75rem;
|
||||
|
||||
Reference in New Issue
Block a user