Skip to content

Instantly share code, notes, and snippets.

@tabula-rasa
Created February 24, 2018 20:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tabula-rasa/61d2ab25aac779fdf9899f4e87ab8306 to your computer and use it in GitHub Desktop.
Save tabula-rasa/61d2ab25aac779fdf9899f4e87ab8306 to your computer and use it in GitHub Desktop.
Mithril JS toaster-like notifications with proper css fade-out/fade-in animation
.m-notifications {
position: fixed;
bottom: 20px;
right: 20px;
display: flex;
flex-direction: column;
align-items: flex-end;
z-index: 10;
.m-notification {
width: auto;
margin-bottom: 0.25rem;
max-width: 400px;
cursor: pointer;
animation: fade-in 0.3s;
&:hover {
box-shadow: 1px 1px 2px rgba(0,0,0,0.3);
}
&.destroy {
animation: fade-out 0.3s;
}
&.info {
color: #0c5460;
background-color: #d1ecf1;
padding: 0.75rem 1.25rem;
border: 1px solid #bee5eb;
border-radius: 0.25rem;
}
&.warning {
color: #856404;
background-color: #fff3cd;
padding: 0.75rem 1.25rem;
border: 1px solid #ffeeba;
border-radius: 0.25rem;
}
&.danger {
color: #721c24;
background-color: #f8d7da;
padding: 0.75rem 1.25rem;
border: 1px solid #f5c6cb;
border-radius: 0.25rem;
}
&.success {
color: #155724;
background-color: #d4edda;
padding: 0.75rem 1.25rem;
border: 1px solid #c3e6cb;
border-radius: 0.25rem;
}
}
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
export function guid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
//layout component
import m from 'mithril';
import notifications from './notifications'
const Layout = {
//vnode.attrs -> body component
view: function (vnode) {
return m(".layout", [
//your layout goes here, just add somewhere the component reference:
m(notifications),
]);
}
}
export default Layout;
import m from 'mithril'
import { guid } from './helpers'
let state = {
list: [],
destroy(msg) {
let index = state.list.findIndex(x => x.id === msg.id)
state.list.splice(index, 1)
}
}
export function addSuccess(text, timeout = 3000) {
state.list.push({ id: guid(), type: 'success', text, timeout })
}
export function addInfo(text, timeout = 3000) {
state.list.push({ id: guid(), type: 'info', text, timeout })
}
export function addWarning(text, timeout = 3000) {
state.list.push({ id: guid(), type: 'warning', text, timeout })
}
export function addDanger(text, timeout = 3000) {
state.list.push({ id: guid(), type: 'danger', text, timeout })
}
let Notifications = {
oninit(vnode) {
if (state.list.length == 0) {
//demo messages
addInfo("Info message!")
addWarning("Warning message!")
addDanger("This is danger message! Take care.")
addSuccess("Operation successful.")
}
},
view(vnode) {
let ui = vnode.state
return state.list ?
m('.m-notifications', state.list.map((msg) => {
return m('div', { key: msg.id }, m(Notification, msg)) //wrap in div with key for proper dom updates
})) : null
}
}
let Notification = {
oninit(vnode) {
setTimeout(() => {
Notification.destroy(vnode)
}, vnode.attrs.timeout)
},
notificationClass(type) {
const types = ['info', 'warning', 'success', 'danger']
if (types.indexOf(type) > -1)
return type
return 'info'
},
destroy(vnode) {
vnode.dom.classList.add('destroy')
setTimeout(() => {
state.destroy(vnode.attrs)
m.redraw()
}, 300)
},
view(vnode) {
let ui = vnode.state
let msg = vnode.attrs
return m('.m-notification', { class: ui.notificationClass(msg.type), onclick: () => { ui.destroy(vnode) } }, msg.text)
}
}
export default Notifications
//page component, shows notification
import m from 'mithril'
import { addSuccess } from '../shared/notifications'
const Page = {
view(vnode) {
return m('.page', [
//your page goes here
//show success message on click, or call add{Success|Warning|Info|Danger} somewhere in your code
m('button[type=button]', { onclick: () => {addSuccess('Hey, this is dynamic message!', 5000)}}, 'Show success message')
])
}
}
@tbreuss
Copy link

tbreuss commented Mar 8, 2022

Thanks a lot for this example. I have added it to Mithril.js by Examples and slightly modified (and of course mentioned your work). I hope that is okay with you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment