custom notifications solution

This commit is contained in:
Martin McKeaveney 2020-06-24 16:10:54 +01:00
parent 01d7f80e7b
commit 2c764a787c
4 changed files with 71 additions and 123 deletions

View File

@ -4,7 +4,7 @@
import { Router, basepath } from "@sveltech/routify"
import { routes } from "../routify/routes"
import { store, initialise } from "builderStore"
import NotificationDisplay from "components/common/Notification.svelte";
import NotificationDisplay from "components/common/Notification/NotificationDisplay.svelte";
$basepath = "/_builder"
</script>

View File

@ -1,9 +1,15 @@
import { writable } from 'svelte/store'
import { generate } from "shortid"
export const notificationStore = writable()
export const notificationStore = writable({
notifications: []
})
export function send(message, type = 'default', timeout) {
notificationStore.set({ type, message, timeout })
export function send(message, type = 'default') {
notificationStore.update(state => {
state.notifications = [...state.notifications, { id: generate(), type, message }]
return state
})
}
export const notifier = {

View File

@ -1,119 +0,0 @@
<script>
import { notificationStore } from "builderStore/store/notifications"
import { onMount, onDestroy } from "svelte"
import { fade } from "svelte/transition"
export let themes = {
danger: "#bb2124",
success: "#22bb33",
warning: "#f0ad4e",
info: "#5bc0de",
default: "#aaaaaa",
}
export let timeout = 3000
let count = 0
let notifications = []
let unsubscribe
function createToast(msg, theme, to) {
const background = themes[theme] || themes["default"]
const id = count
notifications = [
{
id,
msg,
background,
timeout: to || timeout,
width: "100%",
},
...notifications,
]
setTimeout(() => removeNotification(id), to || timeout)
count = count + 1
}
unsubscribe = notificationStore.subscribe(value => {
if (!value) {
return
}
createToast(value.message, value.type, value.timeout)
notificationStore.set()
})
onDestroy(unsubscribe)
function removeNotification(id) {
notifications = notifications.filter(t => t.id != id)
}
</script>
<ul class="notifications">
{#each notifications as toast (toast.id)}
<li class="toast" style="background: {toast.background};" out:fade>
<div class="content">{toast.msg}</div>
</li>
{/each}
</ul>
<style>
:global(.notifications) {
width: 40vw;
list-style: none;
position: fixed;
top: 0;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
padding: 0;
z-index: 9999;
}
:global(.notifications) > .toast {
position: relative;
margin: 10px;
min-width: 40vw;
position: relative;
animation: animate-in 350ms forwards;
color: #fff;
}
:global(.notifications) > .toast > .content {
padding: 10px;
display: block;
font-weight: 500;
}
:global(.notifications) > .toast:before,
:global(.notifications) > .toast:after {
content: "";
position: absolute;
z-index: -1;
top: 50%;
bottom: 0;
left: 10px;
right: 10px;
border-radius: 100px / 10px;
}
:global(.notifications) > .toast:after {
right: 10px;
left: auto;
transform: skew(8deg) rotate(3deg);
}
@keyframes animate-in {
0% {
width: 0;
opacity: 0;
transform: scale(1.15) translateY(20px);
}
100% {
width: 40vw;
opacity: 1;
transform: scale(1) translateY(0);
}
}
</style>

View File

@ -0,0 +1,61 @@
<script>
import { notificationStore } from "builderStore/store/notifications"
import { onMount, onDestroy } from "svelte"
import { fade } from "svelte/transition"
export let themes = {
danger: "#E26D69",
success: "#84C991",
warning: "#f0ad4e",
info: "#5bc0de",
default: "#aaaaaa",
}
export let timeout = 3000
$: if ($notificationStore.notifications.length) {
setTimeout(() => {
notificationStore.update(state => {
state.notifications.shift();
state.notifications = state.notifications
return state;
})
}, timeout)
}
</script>
<ul class="notifications">
{#each $notificationStore.notifications as notification (notification.id)}
<li class="toast" style="background: {themes[notification.type]};" transition:fade>
<div class="content">{notification.message}</div>
{#if notification.icon}
<i class={notification.icon} />
{/if}
</li>
{/each}
</ul>
<style>
.notifications {
width: 40vw;
list-style: none;
position: fixed;
top: 0;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
padding: 0;
z-index: 9999;
}
.toast {
margin-bottom: 10px;
}
.content {
padding: 10px;
display: block;
font-weight: 500;
}
</style>