Adding duration, ids, error and info styling to Toast messages.

This commit is contained in:
Bradley Shellnut 2021-07-29 10:50:22 -07:00
parent 39d2fab7bf
commit 32b7a187e0
4 changed files with 62 additions and 36 deletions

View file

@ -2,23 +2,21 @@
import { fly, fade } from 'svelte/transition'; import { fly, fade } from 'svelte/transition';
import { flip } from 'svelte/animate'; import { flip } from 'svelte/animate';
import Portal from '../Portal.svelte'; import Portal from '../Portal.svelte';
import { toast } from './toast';
import ToastMessage from './ToastMessage.svelte'; import ToastMessage from './ToastMessage.svelte';
import { toast } from './toast';
export let duration = 1000;
</script> </script>
<Portal> <Portal>
<div class="toast-wrapper"> <div class="toast-wrapper">
{#each $toast as message (message)} {#each $toast as message (message.id)}
<div <div
on:click={toast.remove} on:click={() => toast.remove(message.id)}
animate:flip
out:fade
in:fly={{ opacity: 0, x: 100 }} in:fly={{ opacity: 0, x: 100 }}
class="toast" out:fade
animate:flip
class={`toast ${message.type.toLowerCase()}`}
> >
<ToastMessage {message} {duration} /> <ToastMessage {message} />
</div> </div>
{/each} {/each}
</div> </div>
@ -32,10 +30,18 @@
} }
.toast { .toast {
overflow: hidden;
position: relative;
margin-bottom: 1rem; margin-bottom: 1rem;
color: white;
background: var(--toast-background, #625df5);
padding: 20px; padding: 20px;
border-radius: 15px; border-radius: 15px;
background: white;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.3); box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.3);
} }
.toast.error {
background: var(--toast-error-background, #e54b4b);
color: black;
}
</style> </style>

View file

@ -1,23 +1,32 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { toast } from './toast';
import { tweened } from 'svelte/motion'; import { tweened } from 'svelte/motion';
import { toast } from './toast';
export let message;
export let message = ''; let progress = tweened(100, { duration: message.duration });
export let duration = 1000;
let progress = tweened(100, { duration });
onMount(async () => { onMount(async () => {
await progress.set(0); await progress.set(0);
toast.remove(); toast.remove(message.id);
}); });
</script> </script>
<div style={`width: ${$progress}%; height: 10px; background: green;`} /> <div class="progress" style={`width: ${$progress}%;`} />
<p>{message}</p> <p>{message.message}</p>
<style> <style>
.progress {
height: 8px;
background: white;
opacity: 0.3;
position: absolute;
top: 0;
left: 0;
right: 0;
}
p { p {
margin: 0; margin: 0;
} }

View file

@ -1,22 +1,28 @@
import { writable } from "svelte/store"; import { writable } from 'svelte/store';
// Custom store
const newToast = () => { const newToast = () => {
const { subscribe, update } = writable([]); const { subscribe, update } = writable([]);
function send(message) {
update((state) => {
return [...state, message];
});
}
function remove() { function send(message, { duration = 2000, type = 'INFO' } = {}) {
update((state) => { const id = Math.floor(Math.random() * 1000);
let [first, ...rest] = state; const newMessage = {
return [...rest]; id,
}); duration,
} type,
message
};
update((store) => [...store, newMessage]);
}
return { subscribe, send, remove }; function remove(id) {
} update((store) => {
let newStore = store.filter((item) => item.id !== id);
return [...newStore];
});
}
export const toast = newToast(); return { subscribe, send, remove };
};
export const toast = newToast();

View file

@ -27,7 +27,12 @@
</Modal> </Modal>
<Toast duration={3000} /> <Toast duration={3000} />
<button on:click={() => toast.send('New Message' + Math.random())}>New Toast</button>
<button on:click={() => toast.send('NEW MESSAGE!')}>New Toast</button>
<button on:click={() => toast.send('NEW MESSAGE!', { duration: 3000 })}>3000 Duration</button>
<button on:click={() => toast.send('Error MESSAGE!', { duration: 5000, type: 'ERROR' })}
>Error Message</button
>
<!-- <button on:click={() => (isModalOpen = true)}>Open Modal Form</button> --> <!-- <button on:click={() => (isModalOpen = true)}>Open Modal Form</button> -->