Notification Components
Beautiful, responsive notification components built with TailwindCSS and AlpineJS. Perfect for toast notifications, alert banners, and system messages.
1. Toast Notification
A modern toast notification with smooth animations, auto-dismiss functionality, and multiple variants for different message types.
Success!
Your changes have been saved successfully.
<!-- Toast Notification -->
<div id="toast" class="fixed top-4 right-4 z-50 max-w-sm w-full bg-white border border-gray-200 rounded-lg shadow-lg transform transition-all duration-300">
<div class="flex items-start p-4">
<div class="flex-shrink-0">
<svg class="w-6 h-6 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<div class="ml-3 w-0 flex-1">
<p class="text-sm font-medium text-gray-900">Success!</p>
<p class="mt-1 text-sm text-gray-500">Your changes have been saved successfully.</p>
</div>
<div class="ml-4 flex-shrink-0 flex">
<button onclick="hideToast()" class="inline-flex text-gray-400 hover:text-gray-500">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
</div>
<!-- Trigger Button -->
<button onclick="showToast()" class="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors">
Show Success Toast
</button>
<script>
function showToast() {
const toast = document.getElementById('toast');
toast.classList.remove('opacity-0', 'translate-y-2');
toast.classList.add('opacity-100', 'translate-y-0');
setTimeout(() => {
hideToast();
}, 3000);
}
function hideToast() {
const toast = document.getElementById('toast');
toast.classList.remove('opacity-100', 'translate-y-0');
toast.classList.add('opacity-0', 'translate-y-2');
}
</script>
<template>
<!-- Toast Notification -->
<div v-show="showToast" class="fixed top-4 right-4 z-50 max-w-sm w-full bg-white border border-gray-200 rounded-lg shadow-lg transform transition-all duration-300" :class="{ 'opacity-100 translate-y-0': showToast, 'opacity-0 translate-y-2': !showToast }">
<div class="flex items-start p-4">
<div class="flex-shrink-0">
<svg class="w-6 h-6 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<div class="ml-3 w-0 flex-1">
<p class="text-sm font-medium text-gray-900">{{ toastMessage.title }}</p>
<p class="mt-1 text-sm text-gray-500">{{ toastMessage.message }}</p>
</div>
<div class="ml-4 flex-shrink-0 flex">
<button @click="hideToast" class="inline-flex text-gray-400 hover:text-gray-500">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
</div>
<!-- Trigger Button -->
<button @click="showSuccessToast" class="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors">
Show Success Toast
</button>
</template>
<script setup>
import { ref } from 'vue';
const showToast = ref(false);
const toastMessage = ref({
title: 'Success!',
message: 'Your changes have been saved successfully.'
});
const showSuccessToast = () => {
showToast.value = true;
setTimeout(() => {
showToast.value = false;
}, 3000);
};
const hideToast = () => {
showToast.value = false;
};
</script>
import React, { useState } from 'react';
export default function ToastNotification() {
const [showToast, setShowToast] = useState(false);
const [toastMessage, setToastMessage] = useState({
title: 'Success!',
message: 'Your changes have been saved successfully.'
});
const showSuccessToast = () => {
setShowToast(true);
setTimeout(() => {
setShowToast(false);
}, 3000);
};
const hideToast = () => {
setShowToast(false);
};
return (
<>
<!-- Toast Notification -->
{showToast && (
<div className="fixed top-4 right-4 z-50 max-w-sm w-full bg-white border border-gray-200 rounded-lg shadow-lg transform transition-all duration-300 opacity-100 translate-y-0">
<div className="flex items-start p-4">
<div className="flex-shrink-0">
<svg className="w-6 h-6 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<div className="ml-3 w-0 flex-1">
<p className="text-sm font-medium text-gray-900">{toastMessage.title}</p>
<p className="mt-1 text-sm text-gray-500">{toastMessage.message}</p>
</div>
<div className="ml-4 flex-shrink-0 flex">
<button onClick={hideToast} className="inline-flex text-gray-400 hover:text-gray-500">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
</div>
)}
<!-- Trigger Button -->
<button onClick={showSuccessToast} className="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors">
Show Success Toast
</button>
</>
);
}
2. Alert Banner
Dismissible alert banners for important announcements, warnings, and system messages.
New Feature Available!
We've added a new dashboard feature that allows you to track your progress in real-time. Check it out in your account settings.
<!-- Alert Banner -->
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
<div class="flex items-start">
<div class="flex-shrink-0">
<svg class="w-5 h-5 text-blue-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path>
</svg>
</div>
<div class="ml-3 flex-1">
<h3 class="text-sm font-medium text-blue-800">New Feature Available!</h3>
<div class="mt-2 text-sm text-blue-700">
<p>We've added a new dashboard feature that allows you to track your progress in real-time.</p>
</div>
<div class="mt-4">
<div class="-mx-2 -my-1.5 flex">
<button type="button" class="bg-blue-50 px-2 py-1.5 rounded-md text-sm font-medium text-blue-800 hover:bg-blue-100">
View Details
</button>
<button type="button" class="ml-3 bg-blue-50 px-2 py-1.5 rounded-md text-sm font-medium text-blue-800 hover:bg-blue-100">
Dismiss
</button>
</div>
</div>
</div>
<div class="ml-auto pl-3">
<div class="-mx-1.5 -my-1.5">
<button type="button" class="inline-flex bg-blue-50 rounded-md p-1.5 text-blue-500 hover:bg-blue-100">
<span class="sr-only">Dismiss</span>
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
</div>
</div>
<template>
<!-- Alert Banner -->
<div v-show="showBanner" class="bg-blue-50 border border-blue-200 rounded-lg p-4">
<div class="flex items-start">
<div class="flex-shrink-0">
<svg class="w-5 h-5 text-blue-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path>
</svg>
</div>
<div class="ml-3 flex-1">
<h3 class="text-sm font-medium text-blue-800">{{ alert.title }}</h3>
<div class="mt-2 text-sm text-blue-700">
<p>{{ alert.message }}</p>
</div>
<div class="mt-4">
<div class="-mx-2 -my-1.5 flex">
<button type="button" class="bg-blue-50 px-2 py-1.5 rounded-md text-sm font-medium text-blue-800 hover:bg-blue-100">
{{ alert.primaryAction }}
</button>
<button type="button" class="ml-3 bg-blue-50 px-2 py-1.5 rounded-md text-sm font-medium text-blue-800 hover:bg-blue-100">
{{ alert.secondaryAction }}
</button>
</div>
</div>
</div>
<div class="ml-auto pl-3">
<div class="-mx-1.5 -my-1.5">
<button @click="dismissBanner" type="button" class="inline-flex bg-blue-50 rounded-md p-1.5 text-blue-500 hover:bg-blue-100">
<span class="sr-only">Dismiss</span>
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const showBanner = ref(true);
const alert = ref({
title: 'New Feature Available!',
message: 'We\'ve added a new dashboard feature that allows you to track your progress in real-time.',
primaryAction: 'View Details',
secondaryAction: 'Dismiss'
});
const dismissBanner = () => {
showBanner.value = false;
};
</script>
import React, { useState } from 'react';
export default function AlertBanner() {
const [showBanner, setShowBanner] = useState(true);
const [alert, setAlert] = useState({
title: 'New Feature Available!',
message: 'We\'ve added a new dashboard feature that allows you to track your progress in real-time.',
primaryAction: 'View Details',
secondaryAction: 'Dismiss'
});
const dismissBanner = () => {
setShowBanner(false);
};
if (!showBanner) return null;
return (
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
<div className="flex items-start">
<div className="flex-shrink-0">
<svg className="w-5 h-5 text-blue-400" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clipRule="evenodd" />
</svg>
</div>
<div className="ml-3 flex-1">
<h3 className="text-sm font-medium text-blue-800">{alert.title}</h3>
<div className="mt-2 text-sm text-blue-700">
<p>{alert.message}</p>
</div>
<div className="mt-4">
<div className="-mx-2 -my-1.5 flex">
<button type="button" className="bg-blue-50 px-2 py-1.5 rounded-md text-sm font-medium text-blue-800 hover:bg-blue-100">
{alert.primaryAction}
</button>
<button type="button" className="ml-3 bg-blue-50 px-2 py-1.5 rounded-md text-sm font-medium text-blue-800 hover:bg-blue-100">
{alert.secondaryAction}
</button>
</div>
</div>
</div>
<div className="ml-auto pl-3">
<div className="-mx-1.5 -my-1.5">
<button onClick={dismissBanner} type="button" className="inline-flex bg-blue-50 rounded-md p-1.5 text-blue-500 hover:bg-blue-100">
<span className="sr-only">Dismiss</span>
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
</div>
);
}
3. Notification Badge
Small notification dots and count badges for buttons, icons, and menu items.
<!-- Simple notification dot -->
<div class="relative">
<button class="relative px-4 py-2 bg-violet text-white rounded-lg font-bold">
Inbox
<span class="absolute -top-1 -right-1 w-3 h-3 bg-red-500 rounded-full border-2 border-white"></span>
</button>
</div>
<!-- Notification with count -->
<div class="relative">
<button class="relative px-4 py-2 bg-gray-200 text-black rounded-lg font-bold">
Messages
<span class="absolute -top-2 -right-2 min-w-[1.5rem] h-6 bg-red-500 text-white text-xs font-bold rounded-full flex items-center justify-center border-2 border-white">12</span>
</button>
</div>
<!-- Large count -->
<div class="relative">
<button class="relative px-4 py-2 bg-blue-500 text-white rounded-lg font-bold">
Notifications
<span class="absolute -top-2 -right-2 min-w-[1.5rem] h-6 bg-orange-500 text-white text-xs font-bold rounded-full flex items-center justify-center border-2 border-white">99+</span>
</button>
</div>
<template>
<div class="flex items-center gap-6">
<!-- Simple notification dot -->
<div class="relative">
<button class="relative px-4 py-2 bg-violet text-white rounded-lg font-bold">
Inbox
<span v-if="inboxCount > 0" class="absolute -top-1 -right-1 w-3 h-3 bg-red-500 rounded-full border-2 border-white"></span>
</button>
</div>
<!-- Notification with count -->
<div class="relative">
<button class="relative px-4 py-2 bg-gray-200 text-black rounded-lg font-bold">
Messages
<span v-if="messageCount > 0" class="absolute -top-2 -right-2 min-w-[1.5rem] h-6 bg-red-500 text-white text-xs font-bold rounded-full flex items-center justify-center border-2 border-white">
{{ messageCount > 99 ? '99+' : messageCount }}
</span>
</button>
</div>
<!-- Large count -->
<div class="relative">
<button class="relative px-4 py-2 bg-blue-500 text-white rounded-lg font-bold">
Notifications
<span v-if="notificationCount > 0" class="absolute -top-2 -right-2 min-w-[1.5rem] h-6 bg-orange-500 text-white text-xs font-bold rounded-full flex items-center justify-center border-2 border-white">
{{ notificationCount > 99 ? '99+' : notificationCount }}
</span>
</button>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const inboxCount = ref(1);
const messageCount = ref(12);
const notificationCount = ref(150);
</script>
import React, { useState } from 'react';
export default function NotificationBadge() {
const [counts, setCounts] = useState({
inbox: 1,
messages: 12,
notifications: 150
});
const formatCount = (count) => count > 99 ? '99+' : count;
return (
<div className="flex items-center gap-6">
<!-- Simple notification dot -->
<div className="relative">
<button className="relative px-4 py-2 bg-violet text-white rounded-lg font-bold">
Inbox
{counts.inbox > 0 && (
<span className="absolute -top-1 -right-1 w-3 h-3 bg-red-500 rounded-full border-2 border-white"></span>
)}
</button>
</div>
<!-- Notification with count -->
<div className="relative">
<button className="relative px-4 py-2 bg-gray-200 text-black rounded-lg font-bold">
Messages
{counts.messages > 0 && (
<span className="absolute -top-2 -right-2 min-w-[1.5rem] h-6 bg-red-500 text-white text-xs font-bold rounded-full flex items-center justify-center border-2 border-white">
{formatCount(counts.messages)}
</span>
)}
</button>
</div>
<!-- Large count -->
<div className="relative">
<button className="relative px-4 py-2 bg-blue-500 text-white rounded-lg font-bold">
Notifications
{counts.notifications > 0 && (
<span className="absolute -top-2 -right-2 min-w-[1.5rem] h-6 bg-orange-500 text-white text-xs font-bold rounded-full flex items-center justify-center border-2 border-white">
{formatCount(counts.notifications)}
</span>
)}
</button>
</div>
</div>
);
}
4. System Message Banner
System-wide message banners for maintenance notices, updates, and important announcements.
Scheduled Maintenance
Our system will be undergoing maintenance from 2:00 AM to 4:00 AM EST. Some features may be temporarily unavailable.
<!-- System Message Banner -->
<div class="bg-gradient-to-r from-yellow-400 to-orange-500 border border-yellow-500 rounded-lg p-4 shadow-lg">
<div class="flex items-center justify-between">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="w-6 h-6 text-yellow-800" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-yellow-800">Scheduled Maintenance</h3>
<div class="mt-1 text-sm text-yellow-700">
<p>Our system will be undergoing maintenance from 2:00 AM to 4:00 AM EST.</p>
</div>
</div>
</div>
<div class="ml-auto pl-3">
<div class="-mx-1.5 -my-1.5">
<button type="button" class="inline-flex rounded-md p-1.5 text-yellow-800 hover:bg-yellow-300">
<span class="sr-only">Dismiss</span>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
</div>
</div>
<template>
<!-- System Message Banner -->
<div v-show="showMessage" class="bg-gradient-to-r from-yellow-400 to-orange-500 border border-yellow-500 rounded-lg p-4 shadow-lg">
<div class="flex items-center justify-between">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="w-6 h-6 text-yellow-800" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-yellow-800">{{ systemMessage.title }}</h3>
<div class="mt-1 text-sm text-yellow-700">
<p>{{ systemMessage.message }}</p>
</div>
</div>
</div>
<div class="ml-auto pl-3">
<div class="-mx-1.5 -my-1.5">
<button @click="dismissMessage" type="button" class="inline-flex rounded-md p-1.5 text-yellow-800 hover:bg-yellow-300">
<span class="sr-only">Dismiss</span>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const showMessage = ref(true);
const systemMessage = ref({
title: 'Scheduled Maintenance',
message: 'Our system will be undergoing maintenance from 2:00 AM to 4:00 AM EST. Some features may be temporarily unavailable.'
});
const dismissMessage = () => {
showMessage.value = false;
};
</script>
import React, { useState } from 'react';
export default function SystemMessageBanner() {
const [showMessage, setShowMessage] = useState(true);
const [systemMessage, setSystemMessage] = useState({
title: 'Scheduled Maintenance',
message: 'Our system will be undergoing maintenance from 2:00 AM to 4:00 AM EST. Some features may be temporarily unavailable.'
});
const dismissMessage = () => {
setShowMessage(false);
};
if (!showMessage) return null;
return (
<div className="bg-gradient-to-r from-yellow-400 to-orange-500 border border-yellow-500 rounded-lg p-4 shadow-lg">
<div className="flex items-center justify-between">
<div className="flex items-center">
<div className="flex-shrink-0">
<svg className="w-6 h-6 text-yellow-800" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" />
</svg>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-yellow-800">{systemMessage.title}</h3>
<div className="mt-1 text-sm text-yellow-700">
<p>{systemMessage.message}</p>
</div>
</div>
</div>
<div className="ml-auto pl-3">
<div className="-mx-1.5 -my-1.5">
<button onClick={dismissMessage} type="button" className="inline-flex rounded-md p-1.5 text-yellow-800 hover:bg-yellow-300">
<span className="sr-only">Dismiss</span>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
</div>
);
}