Simple toaster in vanilla JavaScript for modern browsers.
- π¦ Simple and elegant
- β‘ Lightweight, 2kb gzipped CSS + JS
- π Modern
- π¦ Zero Dependencies
- π Compatible with all modern UI frameworks and libraries
- π¨ Easily customizable with themes and custom CSS
Check out the demo page. You can use it to play around with different kinds of toasts.
Latest and the greatest.
- Install by
yarn add @ajmey/toaster, ornpm i @ajmey/toaster --save. - Load the toaster:
import toaster from "@ajmey/toaster". - Call any toast, eg
toaster.success("Done!", { dismiss: 1500 }).
Using the default export above, the CSS & JS are loaded automatically. This is the fastest way to get started, but the final bundle is a little larger. Ideally, you should load the CSS and the JS separately:
Load CSS
<link rel="stylesheet" href="node_modules/@ajmey/toaster/themes/theme-default.min.css">or if you are using a bundler like Webpack:
import "@ajmey/toaster/themes/theme-default.min.css";Then, use in JS:
JS
import { useToaster } from "@ajmey/toaster/toaster";
/* factory function `useToaster` does not inject CSS */
const toaster = useToaster({animation: "appear", theme: "default"});
toaster.success();Please check out the module formats and initialization sections for more details.
The toaster object has the following methods for invoking a toast:
successfailureinfowarning
The above methods all have the following signature:
[toastType](message?: string, options?: object) -> Promise<DOM Node>
message:stringthe message to showoptions(optional):objectplain object defining the options:options.dismiss:numberauto dismiss a toast afterdismissmilliseconds. If the value is falsy, auto-dismiss is disabled. All toasts, except the Success toast, are dismissed by default after1500ms.options.title:stringtitle to be used for the toast.options.theme:stringyou can override the theme used in initializationoptions.animation:stringyou can also override the animation used initially
Return Value: each method will return a promise that resolves to the wrapper DOM element holding the toaster. The wrapper node is useful if you use set dismiss to false because you will have access to the wrapper node at that point.
Examples:
toaster.failure("This is the message body". { title: "Error!", dismiss: false, animation: "appear", theme: "dark"});
toaster.success("Todo item was created!");
toaster.info();
toaster.failure("Something went wrong", { dismiss: false})
.then(wrapperNode => console.log(wrapperNode));clear():
If you want to clear the active toast, simply call toaster.clear(). Returns a promise when the toasts are removed. Resolves with the number of toasts removed.
Example
toaster.clear().then(count => console.log("cleared toasters: ", count));on(eventName, callback): can be used to add event handlers:
-
eventName:stringthe event name, possible values are:beforeLoad,loaded,beforeCleared,cleared. -
callback:functionthe event handler callback to be called
Examples:
import toaster from "@ajmey/toaster";
toaster.on("beforeLoad", () => {
console.log("before loaded");
});
toaster.on("loaded", () => {
console.log("toaster loaded.");
});
toaster.on("beforeClear", () => {
console.log("beforeClear");
});
toaster.on("cleared", () => {
console.log("toast cleared.");
});There are two ways that you can use a toaster object:
-
useToasterfactory function is available in@ajmey/toaster/toaster. The factory function does not inject any css by default unless aninjectStylesfunction is given,useToaster(options?: object, injectStyles?: function):options.theme:string, theme name, egdefault,dark, etc. If no value is given,defaultis used.options.animation:string, defining the name of the animation. Defaults toappearif no value is set.
The
injectStylesfunction can be passed in order to inject custom css to the page. Please seegh-pages/index.dev3.htmlfor usage example.Basic example:
import { useToaster } from "@ajmey/toaster/toaster"; const toaster = useToaster({ theme: "dark", animation: "appear" }); toaster.success("hello world!");
-
Using the default import
The default export on
@ajmey/toasteris atoasterobject with all default values. If you use this method, the CSS is also automatically injected to the page and the toaster instance is already initialized:Example:
JS
import toaster from "@ajmey/toaster"; toaster.success("Hello!");
You can override the colors of the toaster by including your own css after the toaster's. For example, if you want to create a light theme, you can do:
CSS
.ajmtoaster.theme-light,
.ajmtoaster.theme-default {
--ajmt-white: #fff;
--ajmt-success: green;
--ajmt-failure: red;
--ajmt-warning: yellow;
--ajmt-info: blue;
/* transition properties */
--ajmt-duration: 400ms;
--ajmt-easing: ease-in-out;
}In the example above, we are also including .theme-default to account for all possible ways that the module could be loaded.
By default, toaster uses the appear animation. You can create new animations using the following selectors:
.ajmtoaster.--animation-slide-down,
.ajmtoaster.--animation-slide-down.--active {
transition: transform var(--ajmt-duration) var(--ajmt-easing) 0ms,
opacity var(--ajmt-duration) var(--ajmt-easing) 50ms;
}
.ajmtoaster.--animation-slide-down {
opacity: 0;
transform: translateY(-20px);
}
.ajmtoaster.--animation-slide-down.--active {
opacity: 1;
transform: translateY(0);
}In the example above, we create a new animation called slide-down. Once the CSS is defined, you can pass animation as an option to useToaster:
import { useToaster } from "@ajmey/toaster/toaster";
const toaster = useToaster({ animation: "slide-down" });It's very easy to override every CSS rule, since all of them use a single class name with one or two modifiers max:
.ajmtoaster: the main wrapper around the whole toaster..ajmtoaster__inner: inner content of the toaster..ajmtoaster__inner.--success: success modifier.ajmtoaster__inner.--failure: failure modifier.ajmtoaster__inner.--warning: warning modifier.ajmtoaster__inner.--info: info modifier
.ajmtoaster__title: the title for the toaster..ajmtoaster__message: toaster message..ajmtoaster__dismiss: the button to dismiss the toaster.
Every single class above have a theme modifier as well, in the form of .[classname].[theme]. For example:
.ajmtoaster.theme-dark.ajmtoaster__inner.theme-dark.ajmtoaster__inner.--success.theme-dark- etc
This package is available both in ES and UMD formats:
ESM
import toaster from "@ajmey/toaster"; // default import
import {useToaster, injectStyles} from "@ajmey/toaster/toaster";All the ESM modules are importable from the root @ajmey/toaster/<module>:
- index.js
- toaster.js
- themes.js
UDM
All the UMD formats are available in the node_modules/@ajmey/toaster/umd. When loaded in the global context, window.ajmtoaster is available. For example:
<script src="node_modules/@ajmey/toaster/umd/index.js"></script>
<script>
console.log(window.ajmtoaster.themes.baseCss.length);
window.toaster = window.ajmtoaster.default;
window.toaster2 = window.ajmtoaster.useToaster({ animation: "appear", theme: "dark"})
window.toaster2.failure("Something went wrong.");
</script>If using JS/CSS separately, the smallest total size will be: 1.4K + 772B = 2.172 kb:
- esm/toaster.min.js.gz: 1.4K
- themes/theme-default.min.css.gz: 772B
- Make sure to install the latest LTS version of Node:
nvm install --lts. - Install yarn with
npm i -g yarn. - Install dependencies with
yarn install. - Run
yarn devto start rollup and css watch. - Update code in the
src/folder. - Run the examples (gh-pages) locally:
yarn serverd - Open
http://localhost:8080/gh-pages/index.dev*.htmlto check the functionality. - To run the e2e tests in watch mode, run
yarn server && yarn e2ew. TestCafe will start testing whats served at 8080.
To publish a new version:
yarn prepand git add and commit all.npm version patch|minor|major&&yarn build&&npm publish --access=public