A 'site message banner' component that can display multiple messages, animates their closing, and remembers closed messages via localStorage
by philw_
HTML
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.4.6/tailwind.min.css">
<script src="https://cdn.jsdelivr.net/gh/ctidigital/outline.js@1.3.0/outline.js"></script>
<script
src="https://cdn.jsdelivr.net/npm/alpinejs@2.3.3/dist/alpine.js"
integrity="sha256-YMtt6o4gwAMeWbjhX1r2n/ZgaCCA7BEKCRsLVN+qeDA="
crossorigin="anonymous"
></script>
<div x-data="messageBannerData()">
<!--
The messages would come from a CMS that would supply the hashes
used in the x-ref values and x-show functions. The hashes represent
the content of the message and serve as a unique ID.
-->
<div
x-ref="20482A0"
x-show="isVisible('20482A0')"
class="bg-red-200 px-8 duration-200 ease-in transition-all overflow-hidden"
>
<div class="py-4 flex space-x-3">
<div class="w-6 text-red-800" data-feather="alert-triangle"></div>
<p class="flex-grow" data-message-text>Pre-closed message</p>
<button
class="duration-100 ease-in-out focus:scale-110 hover:scale-110 transform transition-transform"
@click="close('20482A0')"
aria-label="Close"
>
<div data-feather="x"></div>
</button>
</div>
</div>
<div
x-ref="36EFA59"
x-show="isVisible('36EFA59')"
class="bg-red-200 px-8 duration-200 ease-in transition-all overflow-hidden"
>
<div class="py-4 flex space-x-3">
<div class="w-6 text-red-800" data-feather="alert-triangle"></div>
<p class="flex-grow" data-message-text>Message banner one</p>
<button
class="duration-100 ease-in-out focus:scale-110 hover:scale-110 transform transition-transform"
@click="close('36EFA59')"
aria-label="Close"
>
<div data-feather="x"></div>
</button>
</div>
</div>
<div
x-ref="135C4C1"
x-show="isVisible('135C4C1')"
class="bg-green-200 px-8 duration-200 ease-in transition-all overflow-hidden"
>
<div class="py-4 flex space-x-3">
<div class="w-6...
JavaScript
function messageBannerData() {
return {
closedMessages: {
...JSON.parse(window.localStorage.getItem('closedMessages')),
// We 'prehide' one message, perhaps based on server-side logic:
'20482A0': false,
},
close(hash) {
const elem = this.$refs[hash];
elem.style.height = elem.scrollHeight + 'px';
window.setTimeout(() => {
elem.style.height = '0';
}, 50);
elem.addEventListener('transitionend', () => {
this.closedMessages[hash] = false;
window.localStorage.setItem('closedMessages', JSON.stringify(this.closedMessages));
});
},
isVisible(hash) {
return !this.closedMessages.hasOwnProperty(hash);
},
resetDemo() {
if (confirm("This will clear the localStorage and reset the demo")) {
window.localStorage.removeItem('closedMessages');
window.setTimeout(() => {
window.location.reload(true);
}, 0);
}
}
}
}