svelte-toast
Simple elegant toast notifications.
A lightweight, unopinionated and performant toast notification component for modern web frontends in
very
little
lines
of
code. Compiled (into UMD),
it's only 19kb minified (8kb gzipped) and can be used in Vanilla JS, or as a Svelte
component.
Because a demo helps better than a thousand API docs: https://zerodevx.github.io/svelte-toast/
Usage
Install the package:
$ npm i -D @zerodevx/svelte-toast
The following are exported:
SvelteToast
as the toast container;toast
as the toast emitter.
Svelte
If you're using this in a Svelte app, import the toast container and place it in your app shell or
root layout.
+layout.svelte
:
<script>
import { SvelteToast } from '@zerodevx/svelte-toast'
const options = {
...
}
</script>
...
<SvelteToast {options} />
Use anywhere in your app - just import the toast emitter.
MyComponent.svelte
:
<script>
import { toast } from '@zerodevx/svelte-toast'
</script>
<button on:click={() => toast.push('Hello world!')}>EMIT TOAST</button>
Vanilla JS
For any other application with a bundler, something like this should work:
import { SvelteToast, toast } from '@zerodevx/svelte-toast'
const app = new SvelteToast({
target: document.body,
props: {
options: {
...
}
}
})
toast.push('Hello world!')
CDN
Or if you prefer to go old-school javascript and a CDN:
<head>
...
<script src="https://cdn.jsdelivr.net/npm/@zerodevx/svelte-toast@0"></script>
<script>
const toastApp = new SvelteToast({
target: document.body,
props: {
options: {
...
}
}
})
toast.push('Hello world!')
</script>
</head>
Theming
In general, use CSS variables - the following (self-explanatory) vars are exposed:
._toastContainer {
top: var(--toastContainerTop, 1.5rem);
right: var(--toastContainerRight, 2rem);
bottom: var(--toastContainerBottom, auto);
left: var(--toastContainerLeft, auto);
z-index: var(--toastContainerZIndex, 9999);
}
._toastItem {
width: var(--toastWidth, 16rem);
height: var(--toastHeight, auto);
min-height: var(--toastMinHeight, 3.5rem);
margin: var(--toastMargin, 0 0 0.5rem 0);
padding: var(--toastPadding, 0);
background: var(--toastBackground, rgba(66, 66, 66, 0.9));
color: var(--toastColor, #fff);
box-shadow: var(
--toastBoxShadow,
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06)
);
border: var(--toastBorder, none);
border-radius: var(--toastBorderRadius, 0.125rem);
}
._toastMsg {
padding: var(--toastMsgPadding, 0.75rem 0.5rem);
}
._toastBtn {
width: var(--toastBtnWidth, 2rem);
height: var(--toastBtnHeight, 100%);
font: var(--toastBtnFont, 1rem sans-serif);
}
._toastBtn::after {
content: var(--toastBtnContent, '✕');
}
._toastBar {
background: var(--toastBarBackground, rgba(33, 150, 243, 0.75));
top: var(--toastBarTop, auto);
right: var(--toastBarRight, auto);
bottom: var(--toastBarBottom, 0);
left: var(--toastBarLeft, 0);
height: var(--toastBarHeight, 6px);
width: var(--toastBarWidth, 100%);
}
So to apply your custom theme globally, do something like:
<style>
:root {
--toastBackground: #abcdef;
--toastColor: #123456;
--toastHeight: 300px;
...
}
</style>
To apply CSS overrides to a particular Toast Item (on a per-toast basis), emit the toast with
options:
toast.push('Yo!', {
theme: {
'--toastBackground': 'cyan',
'--toastColor': 'black',
...
}
})
where theme
is an object containing one or more CSS var key/value pairs.
Create Your Own Toast Actions
For convenient composing, you can either push toasts with
user-defined classes (from v0.7
), or create your own common
toast actions by stubbing them out. For example:
my-theme.js
import { toast } from '@zerodevx/svelte-toast'
export const success = m => toast.push(m, {
theme: {
'--toastBackground': 'green',
'--toastColor': 'white',
'--toastBarBackground': 'olive'
}
})
export const warning = m => toast.push(m, { theme: { ... } })
export const failure = m => toast.push(m, { theme: { ... } })
Then simply import these stubs in your consuming component:
import { success, warning, failure } from './my-theme'
success('It works!')
Rich HTML
Toast messages can be in rich HTML too - for example:
toast.push(`<strong>You won the jackpot!</strong><br>
Click <a href="#" target="_blank">here</a> for details! 😛`)
Custom Fonts and Styles
In a Svelte app, the quickest way to apply custom styles is to wrap the toast container then apply
styles on the wrapper:
<style>
.wrap {
display: contents;
font-family: Roboto, sans-serif;
font-size: 0.875rem;
--toastBackground: pink;
...
}
.wrap :global(strong) {
font-weight: 600;
}
</style>
<div class="wrap">
<SvelteToast />
</div>
In Vanilla JS, simply apply your styles to the ._toastContainer
class:
._toastContainer {
font-family: Roboto, sans-serif;
--toastBackground: yellow;
...
}
Features
New from v0.4
Supporting Multiple Toast Containers
It's now easy to send toasts to different container targets within your app. For example:
<script>
import { SvelteToast, toast } from '@zerodevx/svelte-toast'
toast.push('Yo!')
toast.push('Hey!', { target: 'new' })
</script>
<style>
.wrap {
--toastContainerTop: 0.5rem;
--toastContainerRight: 2rem;
--toastContainerBottom: auto;
--toastContainerLeft: 2rem;
--toastWidth: 100%;
font-size: 0.875rem;
...
}
</style>
<SvelteToast />
<div class="wrap">
<SvelteToast target="new" options={{ duration: 8000, intro: { y: -64 } }} />
</div>
Removing Multiple Toasts
pop()
now accepts a filter function.
toast.pop((i) => i.target !== 'new')
toast.pop(0)
Accepting Object as First Param
push()
and set()
can also take an object as its first parameter.
let id = toast.push('Yo!', { duration: 2000 })
id = toast.push({ msg: 'Yo!', duration: 2000 })
toast.set(id, { msg: 'Waddup!' })
toast.set({ id, msg: 'Waddup!' })
New from v0.5
Pausable Toasts
Progress bar tweens can now be paused when the mouse cursor (on desktop) is hovered over the toast
item. This behaviour is disabled by default. To enable, set option pausable: true
.
toast.push('Hover me!', { pausable: true })
Send Svelte Component as a Message
To support complex UIs or workflows, a Svelte component can be pushed instead of a standard message
if you're using this in a Svelte project. To do so, push options with component
defined:
import MyCustomSvelteComponent from './MyCustomSvelteComponent.svelte'
toast.push({
component: {
src: MyCustomSvelteComponent,
props: { ... },
sendIdTo: 'toastId'
},
...
})
New from v0.6
onpop()
Callback Function
A callback function can be run when a toast is closed. To do so, pass the function to the onpop
toast option:
toast.push('Hello world', {
onpop: (id) => {
console.log(`${id} removed`)
},
...
})
New from v0.7
Styling with User-Defined Classes
Custom class names can now be passed into each toast item. Very useful for composing toast actions,
or implementing CSS-only dark modes.
<script>
toast.push('Foo', { classes: ['info'] })
toast.push('Bar', { classes: ['warn'] })
</script>
<SvelteToast options={{ classes: ['log'] }} />
<style>
:global(.log.info) {
--toastBackground: green;
}
:global(.log.warn) {
--toastBackground: red;
}
</style>
New from v0.8
Auto-pause Toasts when Page Hidden
This feature uses the
Page Visibility API (if it's
supported) to pause/resume a toast whenever the browser tab visibility changes - allowing one to
emit notifications in the background without it being dismissed prematurely. This now happens
automatically and is default behaviour, since notifications should by nature ensure that they're
seen.
Customise Dismiss Button
Additional CSS vars are exposed - specifically, --toastBtnContent
allows the '✕' default character
to be changed. As with CSS content
keys for pseudo elements, url()
can be used to load external
or inline icons.
<script>
import { toast, SvelteToast } from '@zerodevx/svelte-toast'
const options = {
theme: {
'--toastBtnContent': `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' ...")`
}
}
</script>
<button on:click={() => toast.push('Ping!')}>PONG</button>
<SvelteToast {options} />
Toast Options
const options = {
duration: 4000,
initial: 1,
next: 0,
pausable: false,
dismissable: true,
reversed: false,
intro: { x: 256 },
theme: {},
classes: []
}
Toast Methods
const id = toast.push(msg, { ...options })
toast.pop(id || fn || undefined)
toast.set(id, { ...options })
Development
Standard Github
contribution workflow
applies.
Tests
Testing is through Cypress. To run the tests headlessly:
$ npm run test
Changelog
Please refer to the releases page.
License
ISC