vikunja/frontend/src/components/misc/Notification.vue

100 lines
2.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<Teleport :to="teleportTarget">
<Notifications
position="bottom left"
:max="2"
:ignore-duplicates="true"
class="global-notification"
role="status"
aria-live="polite"
>
<template #body="{ item, close }">
<!-- FIXME: overlay whole notification with button and add event listener on that button instead -->
<div
class="vue-notification-template vue-notification"
:class="[
item.type,
]"
@click="close()"
>
<div
v-if="item.title"
class="notification-title"
>
{{ item.title }}
</div>
<div class="notification-content">
<template v-if="Array.isArray(item.text)">
<template
v-for="(t, k) in item.text"
:key="k"
>
{{ t }}<br>
</template>
</template>
<template v-else>
{{ item.text }}
</template>
<span
v-if="item.duplicates > 0"
class="tw:text-xs tw:font-bold tw:ml-1"
>
×{{ item.duplicates + 1 }}
</span>
</div>
<div
v-if="item.data?.actions?.length > 0"
class="mbs-2 tw:flex tw:justify-end tw:gap-2"
>
<XButton
v-for="(action, i) in item.data.actions"
:key="'action_' + i"
:shadow="false"
class="is-small"
variant="secondary"
@click="action.callback"
>
{{ action.title }}
</XButton>
</div>
</div>
</template>
</Notifications>
</Teleport>
</template>
<script lang="ts" setup>
import {onBeforeUnmount, onMounted, ref} from 'vue'
const teleportTarget = ref<string | HTMLElement>('body')
let observer: MutationObserver | null = null
function syncTeleportTarget() {
const dialogs = document.querySelectorAll<HTMLDialogElement>('dialog.modal-dialog[open]')
teleportTarget.value = dialogs.item(dialogs.length - 1) ?? 'body'
}
onMounted(() => {
syncTeleportTarget()
observer = new MutationObserver(syncTeleportTarget)
observer.observe(document.body, {
attributes: true,
attributeFilter: ['open'],
childList: true,
subtree: true,
})
})
onBeforeUnmount(() => {
observer?.disconnect()
observer = null
})
</script>
<style scoped>
.vue-notification {
z-index: 9999;
}
</style>