How to create a notification with Tailwind CSS and Alpinejs
Learn how to create a notification with Tailwind CSS and Alpinejs, including how to use Alpine.js directives to add and remove notifications dynamically
Creating a Notification with Tailwind CSS and Alpine.js
Notifications are useful for showing messages to users, like success confirmations or error alerts. This tutorial shows how to build a simple notification using Tailwind CSS for styling and Alpine.js for handling the show/hide behavior.
Basic Setup
First, include the notification component in your HTML. Here’s the full code:
<div
class="w-full max-w-xl mx-auto"
x-data="{
open: false,
type: 'success',
title: 'Success!',
message: 'Coffee has been successfully refilled.',
timeout: 4000,
timer: null,
show(payload = {}) {
const d = { type:'success', title:this.title, message:this.message, timeout:this.timeout, ...payload };
this.type = d.type; this.title = d.title; this.message = d.message; this.timeout = d.timeout;
this.open = true;
this.startTimer();
},
close(){ this.open = false; this.clearTimer(); },
clearTimer(){ if(this.timer){ clearTimeout(this.timer); this.timer = null; } },
startTimer(){ this.clearTimer(); if(this.timeout !== false){ this.timer = setTimeout(()=> this.close(), Number(this.timeout)||4000); } }
}"
x-init="window.addEventListener('notify', (e) => show(e.detail||{}))"
>
<!-- Demo buttons -->
<div class="flex flex-wrap items-center justify-center gap-2">
<button
class="px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
@click="show({ type:'success', title:'Saved', message:'Changes stored.' })"
>
Success
</button>
<button
class="px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
@click="show({ type:'info', title:'Heads up', message:'New version available.' })"
>
Info
</button>
<button
class="px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
@click="show({ type:'warning', title:'Check access', message:'Some users lost permissions.' })"
>
Warning
</button>
<button
class="px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
@click="show({ type:'error', title:'Sync failed', message:'Could not reach the server.' })"
>
Error
</button>
</div>
<!-- Notification panel -->
<div
aria-live="assertive"
class="fixed inset-0 flex items-end px-4 py-6 pointer-events-none sm:items-start sm:p-6"
>
<div class="flex flex-col items-center w-full space-y-4 sm:items-end">
<div
x-show="open"
x-transition:enter="transform ease-out duration-300"
x-transition:enter-start="translate-y-2 opacity-0 sm:translate-x-2 sm:translate-y-0"
x-transition:enter-end="translate-y-0 opacity-100 sm:translate-x-0"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@mouseenter="clearTimer()"
@mouseleave="startTimer()"
class="w-full max-w-sm bg-white rounded-lg shadow-lg pointer-events-auto border border-gray-200"
role="status"
aria-live="polite"
>
<div class="p-4">
<div class="flex items-start">
<div class="shrink-0">
<!-- Icon based on type -->
<div x-show="type==='success'" class="text-green-500">✓</div>
<div x-show="type==='info'" class="text-blue-500">ℹ</div>
<div x-show="type==='warning'" class="text-yellow-500">⚠</div>
<div x-show="type==='error'" class="text-red-500">✕</div>
</div>
<div class="ml-3 w-0 flex-1 pt-0.5">
<p class="text-sm font-medium text-gray-900" x-text="title"></p>
<p class="mt-1 text-sm text-gray-500" x-text="message"></p>
</div>
<div class="flex ml-4 shrink-0">
<button
type="button"
@click="close()"
class="inline-flex text-gray-400 hover:text-gray-500"
>
<span class="sr-only">Close</span>
✕
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
How It Works
The notification uses Alpine.js to control when it shows and hides. The x-data
attribute sets up the data and functions:
open
: Controls if the notification is visible.type
: The type of notification (success, info, warning, error).title
andmessage
: The text to show.timeout
: How long before it auto-closes (in milliseconds).show()
: Function to display the notification with custom options.close()
: Function to hide it.startTimer()
andclearTimer()
: Handle the auto-close timer.
Triggering Notifications
You can show notifications in two ways:
- With buttons: Click the demo buttons to see different types.
<button
@click="show({ type:'success', title:'Saved', message:'Changes stored.' })"
>
Success
</button>
- From JavaScript: Use a custom event to trigger it from anywhere.
window.dispatchEvent(
new CustomEvent("notify", {
detail: {
type: "success",
title: "Saved",
message: "All good",
timeout: 4000,
},
})
);
Customizing the Notification
Change the type, title, message, or timeout when calling show()
:
show({
type: "error",
title: "Error",
message: "Something went wrong",
timeout: 5000,
});
Set timeout: false
to keep it open until manually closed.
Animations
The notification slides in and fades out using Tailwind’s transition classes. It pauses the timer when you hover over it, so you can read the message.
This setup gives you a flexible way to show user feedback without reloading the page.
/Michael Andreuzza