forked from tsai/budibase
4 changed files with 71 additions and 123 deletions
@ -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> |
|||
@ -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> |
|||
Loading…
Reference in new issue