#app.container
button(v-on:click="openToast('default')").default Open 'Default'
button(v-on:click="openToast('primary')").primary Open 'Primary'
button(v-on:click="openToast('success')").success Open 'Success'
button(v-on:click="openToast('warning')").warning Open 'Warning'
button(v-on:click="openToast('danger')").danger Open 'Danger'
a-lil-toast(v-bind:messages.sync="messages")
View Compiled
$font-family: Montserrat, sans-serif;;
$spacing: 15px;
$a-lil-toast-max-width: 500px;
$a-lil-toast-padding: 0 20px;
$a-lil-toast-bottom: $spacing;
$a-lil-toast-message-default-color: #ffffff;
$a-lil-toast-message-default-background-color: #404040;
$a-lil-toast-message-padding: $spacing;
$a-lil-toast-message-margin: $spacing 0 0 0;
$a-lil-toast-message-box-shadow: 0 3px 8px rgba(#000000, 0.1);
$a-lil-toast-message-animation: a-lil-toast-show 500ms ease-in-out forwards;
$a-lil-toast-message-primary-color: #ffffff;
$a-lil-toast-message-primary-background-color: #1489ff;
$a-lil-toast-message-success-color: #ffffff;
$a-lil-toast-message-success-background-color: #00ce0d;
$a-lil-toast-message-warning-color: #4c3b03;
$a-lil-toast-message-warning-background-color: #ffe92b;
$a-lil-toast-message-danger-color: #ffffff;
$a-lil-toast-message-danger-background-color: #ff2323;
$a-lil-toast-message-closed-animation: a-lil-toast-hide 500ms ease-in-out forwards;
$a-lil-toast-control-margin-bottom: $spacing;
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,400i,700");
.a-lil-toast {
font-family: $font-family;
width: 100%;
max-width: $a-lil-toast-max-width;
height: 0;
padding: $a-lil-toast-padding;
display: flex;
flex-direction: column-reverse;
position: fixed;
left: 50%;
bottom: $a-lil-toast-bottom;
box-sizing: border-box;
transform: translateX(-50%);
}
.a-lil-toast-message {
width: 100%;
margin: $a-lil-toast-message-margin;
padding: $a-lil-toast-message-padding;
box-sizing: border-box;
box-shadow: $a-lil-toast-message-box-shadow;
transform-origin: bottom center;
&.default {
color: $a-lil-toast-message-default-color;
background-color: $a-lil-toast-message-default-background-color;
}
&.primary {
color: $a-lil-toast-message-primary-color;
background-color: $a-lil-toast-message-primary-background-color;
}
&.success {
color: $a-lil-toast-message-success-color;
background-color: $a-lil-toast-message-success-background-color;
}
&.warning {
color: $a-lil-toast-message-warning-color;
background-color: $a-lil-toast-message-warning-background-color;
}
&.danger {
color: $a-lil-toast-message-danger-color;
background-color: $a-lil-toast-message-danger-background-color;
}
&:not(.closed) {
animation: $a-lil-toast-message-animation;
}
&.closed {
animation: $a-lil-toast-message-closed-animation;
}
}
.a-lil-toast-control {
margin-bottom: $a-lil-toast-control-margin-bottom;
&.title {
font-weight: bold;
}
&.button {
text-align: right;
a {
color: inherit;
font-weight: bold;
text-decoration: none;
outline: none;
&:hover, &:focus, &:active {
text-decoration: underline;
}
}
}
&:last-child {
margin-bottom: 0;
}
}
@keyframes a-lil-toast-show {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes a-lil-toast-hide {
from { opacity: 1; }
to { opacity: 0; }
}
// -----
html, body, .container {
width: 100%;
height: 100%;
padding: 0;
margin: 0
}
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
button {
font-family: $font-family;
font-size: 24px;
font-weight: bold;
width: calc(100% - 30px);
max-width: 360px;
border: none;
padding: 15px;
margin: 5px;
box-sizing: border-box;
&.default {
color: $a-lil-toast-message-default-color;
background-color: $a-lil-toast-message-default-background-color;
&:hover {
background-color: lighten($a-lil-toast-message-default-background-color, 5%);
}
&:active {
background-color: darken($a-lil-toast-message-default-background-color, 5%);
}
}
&.primary {
color: $a-lil-toast-message-primary-color;
background-color: $a-lil-toast-message-primary-background-color;
&:hover {
background-color: lighten($a-lil-toast-message-primary-background-color, 5%);
}
&:active {
background-color: darken($a-lil-toast-message-primary-background-color, 5%);
}
}
&.success {
color: $a-lil-toast-message-success-color;
background-color: $a-lil-toast-message-success-background-color;
&:hover {
background-color: lighten($a-lil-toast-message-success-background-color, 5%);
}
&:active {
background-color: darken($a-lil-toast-message-success-background-color, 5%);
}
}
&.warning {
color: $a-lil-toast-message-warning-color;
background-color: $a-lil-toast-message-warning-background-color;
&:hover {
background-color: lighten($a-lil-toast-message-warning-background-color, 5%);
}
&:active {
background-color: darken($a-lil-toast-message-warning-background-color, 5%);
}
}
&.danger {
color: $a-lil-toast-message-danger-color;
background-color: $a-lil-toast-message-danger-background-color;
&:hover {
background-color: lighten($a-lil-toast-message-danger-background-color, 5%);
}
&:active {
background-color: darken($a-lil-toast-message-danger-background-color, 5%);
}
}
}
}
View Compiled
Vue.component('a-lil-toast', {
props: ['messages'],
data: function() {
return {
closeText: {
en: 'Close',
ja: '閉じる'
}
}
},
methods: {
removeItem: function(id) {
this.messages[id].closed = 'closed';
this.$emit('update:messages', this.messages);
},
messageCloseTimer: function(evt, id, timer) {
let el = evt.target;
let self = this;
if (timer !== 0) {
if (evt.animationName === 'a-lil-toast-show') {
setTimeout(function() {
self.removeItem(id);
}, timer);
}
}
if (evt.animationName === 'a-lil-toast-hide') {
self.messages[id].content = '';
self.messages.splice(id, 1);
self.$emit('update:messages', self.messages);
}
}
},
template: `
<div class="a-lil-toast">
<div class="a-lil-toast-message" v-for="(message, id) in messages" v-bind:class="[message.type, message.closed]" v-on:animationend="messageCloseTimer(event, id, (message.timer) ? message.timer : 0)">
<div class="a-lil-toast-control title" v-if="message.title">{{ message.title }}</div>
<div class="a-lil-toast-control">{{ message.content }}</div>
<div class="a-lil-toast-control button" v-if="message.button">
<a href="#" v-on:click="removeItem(id)">{{ (message.lang) ? closeText[message.lang] : closeText.en }}</a>
</div>
</div>
</div>
`
});
// -----
var app = new Vue({
el: '#app',
data: {
messages: []
},
methods: {
openToast(which) {
// 'content', 'closed', 'type' is required
this.messages.push({
title: 'Hi! This is the title',
content: 'This is the content, this is the content, this is the content',
// To show/hide the 'close' button
button: true,
// HACK: Just the status of the toast if closed or something
closed: '',
// Color of the toast; possible values: 'default', 'primary', 'success', 'warning', and 'danger'.
type: which,
// Default language; Only available as of now is 'en', and 'ja'
lang: 'en',
// Timer (by milliseconds) when the toast will be closed. 0 if never
timer: 0
});
}
}
});
View Compiled
This Pen doesn't use any external CSS resources.