Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 2 additions & 91 deletions packages/ui/src/components/modal/NewModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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 {
Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
17 changes: 17 additions & 0 deletions packages/ui/src/components/nav/PopupNotificationPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
class="popup-notification-group"
:class="{
'has-sidebar': hasSidebar,
'has-modal': hasModalActive,
}"
:style="notificationGroupStyle"
>
<transition-group name="popup-notifs">
<div
Expand Down Expand Up @@ -155,6 +157,7 @@ import {
} from '@modrinth/assets'
import { computed } from 'vue'

import { useModalStack } from '../../composables/modal-stack'
import {
injectPopupNotificationManager,
type PopupNotification,
Expand All @@ -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) =>
Expand Down Expand Up @@ -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;
Expand Down
Loading