You've already forked AstralRinth
forked from didirus/AstralRinth
129
lib/components/base/Notifications.vue
Normal file
129
lib/components/base/Notifications.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div class="vue-notification-group">
|
||||
<transition-group name="notifs">
|
||||
<div
|
||||
v-for="(item, index) in notifications"
|
||||
:key="item.id"
|
||||
class="vue-notification-wrapper"
|
||||
@click="notifications.splice(index, 1)"
|
||||
@mouseenter="stopTimer(item)"
|
||||
@mouseleave="setNotificationTimer(item)"
|
||||
>
|
||||
<div class="vue-notification-template vue-notification" :class="{ [item.type]: true }">
|
||||
<div class="notification-title" v-html="item.title"></div>
|
||||
<div class="notification-content" v-html="item.text"></div>
|
||||
</div>
|
||||
</div>
|
||||
</transition-group>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const notifications = ref([])
|
||||
|
||||
defineExpose({
|
||||
addNotification: (notification) => {
|
||||
const existingNotif = notifications.value.find(
|
||||
(x) =>
|
||||
x.text === notification.text &&
|
||||
x.title === notification.title &&
|
||||
x.type === notification.type
|
||||
)
|
||||
if (existingNotif) {
|
||||
setNotificationTimer(existingNotif)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
notification.id = new Date()
|
||||
|
||||
setNotificationTimer(notification)
|
||||
notifications.value.push(notification)
|
||||
},
|
||||
})
|
||||
|
||||
function setNotificationTimer(notification) {
|
||||
if (!notification) return
|
||||
|
||||
if (notification.timer) {
|
||||
clearTimeout(notification.timer)
|
||||
}
|
||||
|
||||
notification.timer = setTimeout(() => {
|
||||
notifications.value.splice(notifications.value.indexOf(notification), 1)
|
||||
}, 30000)
|
||||
}
|
||||
|
||||
function stopTimer(notif) {
|
||||
clearTimeout(notif.timer)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.vue-notification {
|
||||
background: var(--color-blue) !important;
|
||||
color: var(--color-accent-contrast) !important;
|
||||
|
||||
box-sizing: border-box;
|
||||
text-align: left;
|
||||
font-size: 12px;
|
||||
padding: 10px;
|
||||
margin: 0 5px 5px;
|
||||
|
||||
&.success {
|
||||
background: var(--color-green) !important;
|
||||
}
|
||||
|
||||
&.warn {
|
||||
background: var(--color-orange) !important;
|
||||
}
|
||||
|
||||
&.error {
|
||||
background: var(--color-red) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.vue-notification-group {
|
||||
position: fixed;
|
||||
right: 25px;
|
||||
bottom: 25px;
|
||||
z-index: 99999999;
|
||||
width: 300px;
|
||||
|
||||
.vue-notification-wrapper {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.vue-notification-template {
|
||||
border-radius: var(--radius-md);
|
||||
margin: 0;
|
||||
|
||||
.notification-title {
|
||||
font-size: var(--font-size-lg);
|
||||
margin-right: auto;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.notification-content {
|
||||
margin-right: auto;
|
||||
font-size: var(--font-size-md);
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notifs-enter-active,
|
||||
.notifs-leave-active,
|
||||
.notifs-move {
|
||||
transition: all 0.5s;
|
||||
}
|
||||
.notifs-enter-from,
|
||||
.notifs-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -19,6 +19,7 @@ export { default as FileInput } from './base/FileInput.vue'
|
||||
export { default as DropArea } from './base/DropArea.vue'
|
||||
export { default as Toggle } from './base/Toggle.vue'
|
||||
export { default as CopyCode } from './base/CopyCode.vue'
|
||||
export { default as Notifications } from './base/Notifications.vue'
|
||||
|
||||
export { default as Categories } from './search/Categories.vue'
|
||||
export { default as SearchFilter } from './search/SearchFilter.vue'
|
||||
@@ -52,7 +53,7 @@ export { default as DashboardIcon } from '@/assets/icons/dashboard.svg'
|
||||
export { default as DownloadIcon } from '@/assets/icons/download.svg'
|
||||
export { default as DropdownIcon } from '@/assets/icons/dropdown.svg'
|
||||
export { default as EditIcon } from '@/assets/icons/edit.svg'
|
||||
export { default as ExitIcon } from '@/assets/icons/exit.svg'
|
||||
export { default as ExitIcon } from '@/assets/icons/x.svg'
|
||||
export { default as ExpandIcon } from '@/assets/icons/expand.svg'
|
||||
export { default as ExternalIcon } from '@/assets/icons/external.svg'
|
||||
export { default as EyeIcon } from '@/assets/icons/eye.svg'
|
||||
@@ -60,11 +61,14 @@ export { default as EyeOffIcon } from '@/assets/icons/eye-off.svg'
|
||||
export { default as FileIcon } from '@/assets/icons/file.svg'
|
||||
export { default as FileTextIcon } from '@/assets/icons/file-text.svg'
|
||||
export { default as FilterIcon } from '@/assets/icons/filter.svg'
|
||||
export { default as FolderOpenIcon } from '@/assets/icons/folder-open.svg'
|
||||
export { default as FolderSearchIcon } from '@/assets/icons/folder-search.svg'
|
||||
export { default as GapIcon } from '@/assets/icons/gap.svg'
|
||||
export { default as GitHubIcon } from '@/assets/icons/github.svg'
|
||||
export { default as GlobeIcon } from '@/assets/icons/globe.svg'
|
||||
export { default as GridIcon } from '@/assets/icons/grid.svg'
|
||||
export { default as HamburgerIcon } from '@/assets/icons/hamburger.svg'
|
||||
export { default as HammerIcon } from '@/assets/icons/hammer.svg'
|
||||
export { default as HashIcon } from '@/assets/icons/hash.svg'
|
||||
export { default as HeartIcon } from '@/assets/icons/heart.svg'
|
||||
export { default as HeartHandshakeIcon } from '@/assets/icons/heart-handshake.svg'
|
||||
@@ -78,6 +82,7 @@ export { default as LightBulbIcon } from '@/assets/icons/light-bulb.svg'
|
||||
export { default as LinkIcon } from '@/assets/icons/link.svg'
|
||||
export { default as ListIcon } from '@/assets/icons/list.svg'
|
||||
export { default as LockIcon } from '@/assets/icons/lock.svg'
|
||||
export { default as LogInIcon } from '@/assets/icons/log-in.svg'
|
||||
export { default as LogOutIcon } from '@/assets/icons/log-out.svg'
|
||||
export { default as MoonIcon } from '@/assets/icons/moon.svg'
|
||||
export { default as OmorphiaIcon } from '@/assets/icons/omorphia.svg'
|
||||
@@ -95,10 +100,12 @@ export { default as SettingsIcon } from '@/assets/icons/settings.svg'
|
||||
export { default as ShieldIcon } from '@/assets/icons/shield.svg'
|
||||
export { default as SlashIcon } from '@/assets/icons/slash.svg'
|
||||
export { default as StarIcon } from '@/assets/icons/star.svg'
|
||||
export { default as StopCircleIcon } from '@/assets/icons/stop-circle.svg'
|
||||
export { default as SunIcon } from '@/assets/icons/sun.svg'
|
||||
export { default as SunriseIcon } from '@/assets/icons/sunrise.svg'
|
||||
export { default as TagIcon } from '@/assets/icons/tag.svg'
|
||||
export { default as TagsIcon } from '@/assets/icons/tags.svg'
|
||||
export { default as TerminalSquareIcon } from '@/assets/icons/terminal-square.svg'
|
||||
export { default as TransferIcon } from '@/assets/icons/transfer.svg'
|
||||
export { default as TrashIcon } from '@/assets/icons/trash.svg'
|
||||
export { default as UndoIcon } from '@/assets/icons/undo.svg'
|
||||
@@ -113,5 +120,6 @@ export { default as UsersIcon } from '@/assets/icons/users.svg'
|
||||
export { default as VersionIcon } from '@/assets/icons/version.svg'
|
||||
export { default as WikiIcon } from '@/assets/icons/wiki.svg'
|
||||
export { default as XIcon } from '@/assets/icons/x.svg'
|
||||
export { default as XCircleIcon } from '@/assets/icons/x-circle.svg'
|
||||
|
||||
export { default as ModrinthIcon } from '@/assets/branding/logo.svg'
|
||||
|
||||
Reference in New Issue
Block a user