JSFiddle - React, Tailwind, and code Playground
by Scott Kaye
SCSS
$primary: #ffff00;
$radius: 2px;
.notification-container {
position: fixed;
bottom: 10px;
right: 10px;
width: 300px;
height: 200px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: flex-end;
pointer-events: none;
overflow: hidden;
}
.notification {
pointer-events: all;
box-sizing: border-box;
width: 100%;
border-radius: $radius;
background: linear-gradient(#222, #333);
box-shadow: 0 5px 5px rgba(0,0,0,0.2), inset 0 0 0 1px transparentize($primary, 0.8);
color: #eee;
padding: 8px 12px;
margin-top: 5px;
font: 10pt sans-serif;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
overflow: hidden;
.progress {
position: absolute;
top:0;
left:0;
width: 100%;
height: 1px;
background: linear-gradient(90deg, $primary 75%, transparent);
animation: timeout 3s ease-out 1 forwards;
}
.options {
margin-left: 10px;
button {
border: none;
background: transparent;
color: $primary;
font-weight: 700;
cursor: pointer;
outline: none;
transition: all 100ms ease;
&:hover {
text-shadow: 0 0 15px rgba(255, 255, 0, 0.5);
}
}
}
&.error {
background: linear-gradient(#a00, #800);
}
&.in {
animation: in 250ms ease 1 forwards;
}
&.out {
animation: in 500ms ease 1 forwards reverse;
}
}
@keyframes in {
from {
transform: translateY(50px);
opacity: 0;
}
to {
transform: none;
opacity: 1;
}
}
@keyframes timeout {
to { width: 0 }
}
body {
background: #555;
}
JavaScript
console.clear();
(function (notify, undefined) {
var defaults = {
message: null,
error: false,
refresh: false,
options: [],
timeout: 3000
},
container;
function extendOptions(o1, o2) {
var n = {
message: o2.message,
error: o2.error,
refresh: o2.refresh,
options: o2.options,
timeout: o2.timeout
};
for (var prop in o2)
if (o1.hasOwnProperty(prop)) n[prop] = o1[prop];
return n;
}
function Notif(options) {
var self = this;
var el = document.createElement("div");
el.classList.add("notification");
if (options.error) el.classList.add("error");
el.innerText = options.message;
var progress = document.createElement("div");
progress.classList.add("progress");
el.appendChild(progress);
progress.style.animationDuration = options.timeout + "ms";
if (options.options) {
var buttons = document.createElement("div");
buttons.classList.add("options");
options.options.forEach(function (c) {
var btn = document.createElement("button");
btn.innerText = c.title;
btn.onclick = c.callback.bind(self);
buttons.appendChild(btn);
});
el.appendChild(buttons);
}
this.options = options;
this.hidden = true;
this.element = el;
}
Notif.prototype.hide = function () {
container.removeChild(this.element);
this.hidden = true;
return this;
};
Notif.prototype.show = function () {
if (this.options.refresh) {
var to = this.options.refresh;
delete this.options.refresh;
delete this.options.options;
localStorage["nnp"] = JSON.stringify(this.options);
if (to === true) {
window.location.reload();
} else {
window.location = window.location.origin + window.location.pathname + to;
window.location.reload();
}
return;
}
this.element.classList.add("in");
window.setTimeout(function () {
this.element.classList.remove("in");
}.bind(this), 250);
container.appendChild(this.element);
if (this.options.timeout > 0) {
window.setTimeout(function ()...