@cicciosgamino/snack-bar
Version:
Simple snackbar Lit Element
218 lines (183 loc) • 4.88 kB
JavaScript
import { LitElement, html, css } from 'lit'
class SnackBar extends LitElement {
static get styles () {
return css`
* {
/*
--snack-bk-color: #333;
--snack-txt-color: #f5f5f5;
--snack-font-size: 2.1rem;
--snack-bottom: 0;
--snack-radius: 1px; */
/* base rem unit (10px) */
font-size: 62.5%;
margin: 0;
padding: 0;
box-sizing: border-box;
}
:host {
display: none;
animation-name: fadeOut;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
:host-context([active]) {
/* Handle CSS when host active */
animation-name: fadeIn;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
#snackbar {
border-radius: var(--snack-radius, 1px);
min-width: 100%;
background-color: var(--snack-bk-color, #333);
color: var(--snack-txt-color, #f5f5f5);
text-align: center;
position: fixed;
left: 50%;
transform: translate(-50%, 0);
bottom: var(--snack-bottom, 0);
}
#container {
margin: calc(var(--snack-font-size, 2.1rem) * 1.1);
}
p {
font-size: var(--snack-font-size, 2.1rem);
font-weight: 400;
line-height: var(--snack-font-size, 2.1rem);
}
#snackBtn {
width: var(--snack-font-size, 2.1rem);
height: var(--snack-font-size, 2.1rem);
background: none;
border: none;
cursor: pointer;
position: absolute;
top: calc(var(--snack-font-size, 2.1rem) * 1.3);
right: 3rem;
}
button::after {
content: '';
position: absolute;
top: -50%;
left: -50%;
right: 0;
bottom: 0;
width: calc(var(--snack-font-size, 2.1rem) * 2);
height: calc(var(--snack-font-size, 2.1rem) * 2);
background: #555;
border-radius: 50%;
z-index: -1;
transform: scale(0);
transition: 0.3s cubic-bezier(.95, .32, .37, 1.21);
}
button:hover::after {
transform: scale(1);
}
button svg {
width: var(--snack-font-size, 2.1rem);
height: var(--snack-font-size, 2.1rem);
fill: var(--snack-txt-color, #f5f5f5);
}
button:hover svg {
transform: scale(0.95);
}
@media only screen and (min-width: 649px) {
#snackbar {
min-width: 50%;
}
}
/* Snackbar animation */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
`
}
#timer
static get properties () {
return {
title: {
type: String,
reflect: true
},
active: Boolean,
timing: Number,
closebtn: {
type: Boolean,
reflect: true
}
}
}
constructor () {
super()
this.title = '🌰 ... SnackBar Title' || ''
this.timing = 5000
}
connectedCallback () {
super.connectedCallback()
this.addEventListener('click', this.#deactivate)
console.log('@CLOSE-BTN >> ', this.closebtn)
}
disconnectedCallback () {
clearInterval(this.#timer)
super.disconnectedCallback()
}
updated (changed) {
if (changed.has('active')) {
if (this.hasAttribute('active')) {
this.#activate()
}
}
super.updated()
}
#activate () {
this.style.display = 'block'
clearInterval(this.#timer)
this.#timer = setTimeout(() => {
this.#deactivate()
}, this.timing)
}
#deactivate () {
this.removeAttribute('active')
// listen for the fadeOut animation to end > display none
this.addEventListener('animationend', (event) => {
if (event.animationName === 'fadeOut') {
this.style.display = 'none'
}
})
}
// method close the snackbar
closeSnackbar () {
this.#deactivate()
}
render () {
return html`
<!-- The snackbar -->
<div id="snackbar">
<div id="container">
<p>
${this.title}
</p>
${this.closebtn ?
html`
<!-- deprecated -->
<button
id="snackBtn"
@click=${this.closeSnackbar}>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/>
</svg>
</button>` : null
}
</div>
</div>
`
}
}
customElements.define('snack-bar', SnackBar)