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>
  );
}

We use cookies to improve your experience and analytics. You can accept all cookies or reject non-essential ones.

Learn More