fix: Snackbar notifications hidden behind modal dialogs (#11616)
This commit is contained in:
@@ -20,7 +20,7 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="shadow-sm bg-slate-800 dark:bg-slate-700 rounded-[4px] items-center gap-3 inline-flex mb-2 max-w-[25rem] min-h-[1.875rem] min-w-[15rem] px-6 py-3 text-left"
|
class="shadow-sm bg-n-slate-12 dark:bg-n-slate-7 rounded-lg items-center gap-3 inline-flex mb-2 max-w-[25rem] min-h-[1.875rem] min-w-[15rem] px-6 py-3 text-left"
|
||||||
>
|
>
|
||||||
<div class="text-sm font-medium text-white dark:text-white">
|
<div class="text-sm font-medium text-white dark:text-white">
|
||||||
{{ message }}
|
{{ message }}
|
||||||
@@ -29,7 +29,7 @@ export default {
|
|||||||
<router-link
|
<router-link
|
||||||
v-if="action.type == 'link'"
|
v-if="action.type == 'link'"
|
||||||
:to="action.to"
|
:to="action.to"
|
||||||
class="font-medium cursor-pointer select-none text-woot-500 dark:text-woot-500 hover:text-woot-600 dark:hover:text-woot-600"
|
class="font-medium cursor-pointer select-none text-n-blue-10 hover:text-n-brand"
|
||||||
>
|
>
|
||||||
{{ action.message }}
|
{{ action.message }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|||||||
@@ -1,62 +1,72 @@
|
|||||||
<script>
|
<script setup>
|
||||||
|
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
|
||||||
import WootSnackbar from './Snackbar.vue';
|
import WootSnackbar from './Snackbar.vue';
|
||||||
import { emitter } from 'shared/helpers/mitt';
|
import { emitter } from 'shared/helpers/mitt';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
export default {
|
const props = defineProps({
|
||||||
components: {
|
duration: {
|
||||||
WootSnackbar,
|
type: Number,
|
||||||
},
|
default: 2500,
|
||||||
props: {
|
|
||||||
duration: {
|
|
||||||
type: Number,
|
|
||||||
default: 2500,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
data() {
|
const { t } = useI18n();
|
||||||
return {
|
|
||||||
snackMessages: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
const snackMessages = ref([]);
|
||||||
emitter.on('newToastMessage', this.onNewToastMessage);
|
const snackbarContainer = ref(null);
|
||||||
},
|
|
||||||
unmounted() {
|
|
||||||
emitter.off('newToastMessage', this.onNewToastMessage);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onNewToastMessage({ message: originalMessage, action }) {
|
|
||||||
// FIX ME: This is a temporary workaround to pass string from functions
|
|
||||||
// that doesn't have the context of the VueApp.
|
|
||||||
const usei18n = action?.usei18n;
|
|
||||||
const duration = action?.duration || this.duration;
|
|
||||||
const message = usei18n ? this.$t(originalMessage) : originalMessage;
|
|
||||||
|
|
||||||
this.snackMessages.push({
|
const showPopover = () => {
|
||||||
key: new Date().getTime(),
|
try {
|
||||||
message,
|
const el = snackbarContainer.value;
|
||||||
action,
|
if (el?.matches(':popover-open')) {
|
||||||
});
|
el.hidePopover();
|
||||||
window.setTimeout(() => {
|
}
|
||||||
this.snackMessages.splice(0, 1);
|
el?.showPopover();
|
||||||
}, duration);
|
} catch (e) {
|
||||||
},
|
// ignore
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onNewToastMessage = ({ message: originalMessage, action }) => {
|
||||||
|
const message = action?.usei18n ? t(originalMessage) : originalMessage;
|
||||||
|
const duration = action?.duration || props.duration;
|
||||||
|
|
||||||
|
snackMessages.value.push({
|
||||||
|
key: Date.now(),
|
||||||
|
message,
|
||||||
|
action,
|
||||||
|
});
|
||||||
|
|
||||||
|
nextTick(showPopover);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
snackMessages.value.shift();
|
||||||
|
}, duration);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emitter.on('newToastMessage', onNewToastMessage);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
emitter.off('newToastMessage', onNewToastMessage);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<transition-group
|
<div
|
||||||
name="toast-fade"
|
ref="snackbarContainer"
|
||||||
tag="div"
|
popover="manual"
|
||||||
class="left-0 my-0 mx-auto max-w-[25rem] overflow-hidden absolute right-0 text-center top-4 z-[9999]"
|
class="fixed top-4 left-1/2 -translate-x-1/2 max-w-[25rem] w-[calc(100%-2rem)] text-center bg-transparent border-0 p-0 m-0 outline-none overflow-visible"
|
||||||
>
|
>
|
||||||
<WootSnackbar
|
<transition-group name="toast-fade" tag="div">
|
||||||
v-for="snackMessage in snackMessages"
|
<WootSnackbar
|
||||||
:key="snackMessage.key"
|
v-for="snackMessage in snackMessages"
|
||||||
:message="snackMessage.message"
|
:key="snackMessage.key"
|
||||||
:action="snackMessage.action"
|
:message="snackMessage.message"
|
||||||
/>
|
:action="snackMessage.action"
|
||||||
</transition-group>
|
/>
|
||||||
|
</transition-group>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user