Created
February 24, 2018 20:04
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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') | |
]) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.