Component

Glass Toast

Frosted-glass notification toasts in the glassmorphism design language — translucent backdrop-blur panels with semantic glowing accents, a live countdown progress bar, and pause-on-hover, presented over an animated aurora mesh backdrop.

  • Component
  • Tailwind
  • HTML
  • MIT

What it does

Capabilities

  • Glassmorphism design language
  • Frosted backdrop-blur surfaces
  • Animated aurora mesh backdrop
  • 4 semantic types with glowing accents
  • Countdown progress bar
  • Pause on hover
  • Role=alert for errors/warnings
  • Role=status for success/info
  • Aria-live polite region

Preview

Live component

Interactive preview
Open preview
9:41 100%
devsnips.site/library/tailwind/components/toasts/glass-toast/
fluid · no fixed width 100%
No dependencies Responsive · Focus-visible · Reduced-motion

Install

Add to your project

terminal
npx devsnips add Tailwind/Components/Toasts/glass-toast
registry path: Tailwind/Components/Toasts/glass-toast

Source

Implementation

code.html
<!--
Snippet Name: Glass Toast
Description: Frosted-glass notification toasts with semantic glowing accents, a countdown progress bar, and pause-on-hover, presented over an animated aurora mesh backdrop.
Author: DevSnips Contributors
Usage Example: Call showGlassToast('success'|'error'|'warning'|'info') after async results; the demo panel can be dropped when wiring into a real app.
-->
<div data-glass-toast="glass-toast">
  <!-- Scoped styles: aurora drift animation + reduced-motion guard (pure CSS, no config needed) -->
  <style>
    @keyframes gt-drift-a {
      0%, 100% { transform: translate(0, 0) scale(1); }
      50% { transform: translate(28px, 18px) scale(1.1); }
    }
    @keyframes gt-drift-b {
      0%, 100% { transform: translate(0, 0) scale(1); }
      50% { transform: translate(-24px, -14px) scale(1.06); }
    }
    [data-glass-toast] .gt-blob-a { animation: gt-drift-a 14s ease-in-out infinite; }
    [data-glass-toast] .gt-blob-b { animation: gt-drift-b 18s ease-in-out infinite; }
    @media (prefers-reduced-motion: reduce) {
      [data-glass-toast] *,
      [data-glass-toast] *::before,
      [data-glass-toast] *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
      }
    }
  </style>

  <!-- Toast region (fixed viewport corner) -->
  <div
    class="gt-region pointer-events-none fixed bottom-4 right-4 z-50 flex w-full max-w-sm flex-col items-end gap-3 px-4 sm:px-0"
    role="region"
    aria-label="Notifications"
    aria-live="polite"
  ></div>

  <!-- Demo panel: aurora mesh backdrop + trigger buttons -->
  <div class="relative overflow-hidden rounded-3xl bg-[#0B1026] p-6 ring-1 ring-white/10 sm:p-8">
    <div aria-hidden="true" class="pointer-events-none absolute inset-0">
      <div class="gt-blob-a absolute -left-24 -top-24 h-72 w-72 rounded-full bg-fuchsia-500/40 blur-3xl"></div>
      <div class="gt-blob-b absolute -right-20 top-1/3 h-80 w-80 rounded-full bg-indigo-500/40 blur-3xl"></div>
      <div class="gt-blob-a absolute -bottom-28 left-1/4 h-72 w-72 rounded-full bg-cyan-400/30 blur-3xl"></div>
    </div>

    <div class="relative">
      <p class="text-xs font-semibold uppercase tracking-widest text-cyan-300">Glassmorphism</p>
      <h3 class="mt-2 text-xl font-bold tracking-tight text-white">Deployment notifications</h3>
      <p class="mt-2 max-w-md text-sm leading-relaxed text-slate-300">
        Frosted-glass toasts with a live countdown. Fire one below — hovering a toast pauses its timer.
      </p>

      <div class="mt-6 flex flex-wrap gap-3">
        <button type="button" data-gt-trigger="success" class="inline-flex items-center gap-2 rounded-xl bg-gradient-to-r from-fuchsia-500 to-indigo-500 px-4 py-2.5 text-sm font-semibold text-white shadow-lg shadow-fuchsia-500/25 transition-colors duration-200 hover:from-fuchsia-400 hover:to-indigo-400 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300">
          <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
          Deployment live
        </button>
        <button type="button" data-gt-trigger="error" class="inline-flex items-center gap-2 rounded-xl border border-white/15 bg-white/10 px-4 py-2.5 text-sm font-semibold text-white backdrop-blur transition-colors duration-200 hover:bg-white/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300">
          <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg>
          Build failed
        </button>
        <button type="button" data-gt-trigger="warning" class="inline-flex items-center gap-2 rounded-xl border border-white/15 bg-white/10 px-4 py-2.5 text-sm font-semibold text-white backdrop-blur transition-colors duration-200 hover:bg-white/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300">
          <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/></svg>
          Quota warning
        </button>
        <button type="button" data-gt-trigger="info" class="inline-flex items-center gap-2 rounded-xl border border-white/15 bg-white/10 px-4 py-2.5 text-sm font-semibold text-white backdrop-blur transition-colors duration-200 hover:bg-white/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300">
          <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
          New comment
        </button>
      </div>
    </div>
  </div>

  <script>
    (function () {
      const root = document.currentScript.closest('[data-glass-toast]');
      if (!root) return;
      const region = root.querySelector('.gt-region');
      const DURATION = 5000;

      const variants = {
        success: {
          icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>',
          chip: 'bg-emerald-400/15 text-emerald-300 ring-emerald-300/30',
          bar: 'bg-emerald-400',
          glow: 'shadow-[0_0_36px_-10px_rgba(52,211,153,0.55)]',
        },
        error: {
          icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>',
          chip: 'bg-rose-400/15 text-rose-300 ring-rose-300/30',
          bar: 'bg-rose-400',
          glow: 'shadow-[0_0_36px_-10px_rgba(251,113,133,0.55)]',
        },
        warning: {
          icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/>',
          chip: 'bg-amber-400/15 text-amber-300 ring-amber-300/30',
          bar: 'bg-amber-400',
          glow: 'shadow-[0_0_36px_-10px_rgba(251,191,36,0.55)]',
        },
        info: {
          icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>',
          chip: 'bg-cyan-400/15 text-cyan-300 ring-cyan-300/30',
          bar: 'bg-cyan-400',
          glow: 'shadow-[0_0_36px_-10px_rgba(103,232,249,0.55)]',
        },
      };

      const copy = {
        success: { title: 'Deployment live', body: 'acme-web was deployed to production in 42s.' },
        error: { title: 'Build failed', body: 'Type error in src/api/billing.ts on line 118.' },
        warning: { title: 'Bandwidth at 80%', body: 'Your quota resets in 6 days. Upgrade to avoid throttling.' },
        info: { title: 'New comment', body: 'Priya mentioned you in #design-system.' },
      };

      function dismiss(toast) {
        if (!toast || toast.dataset.dismissed === 'true') return;
        toast.dataset.dismissed = 'true';
        toast.classList.add('translate-x-3', 'opacity-0');
        toast.addEventListener('transitionend', () => toast.remove(), { once: true });
        setTimeout(() => toast.remove(), 400);
      }

      function showGlassToast(type) {
        const v = variants[type] || variants.info;
        const c = copy[type] || copy.info;
        const toast = document.createElement('div');
        toast.className = `pointer-events-auto relative w-full translate-y-3 overflow-hidden rounded-2xl border border-white/15 bg-slate-950/60 opacity-0 shadow-[0_8px_32px_rgba(2,6,23,0.45)] ring-1 ring-white/10 backdrop-blur-2xl transition duration-300 ease-out ${v.glow}`;
        toast.setAttribute('role', type === 'error' || type === 'warning' ? 'alert' : 'status');
        toast.innerHTML = `
          <div class="flex items-start gap-3 p-4">
            <span class="flex h-9 w-9 shrink-0 items-center justify-center rounded-full ring-1 ${v.chip}">
              <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">${v.icon}</svg>
            </span>
            <div class="min-w-0 flex-1">
              <p class="text-sm font-semibold text-white">${c.title}</p>
              <p class="mt-0.5 text-sm leading-relaxed text-slate-200">${c.body}</p>
            </div>
            <button type="button" class="gt-close shrink-0 rounded-lg p-1.5 text-slate-400 transition-colors duration-200 hover:bg-white/10 hover:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300" aria-label="Dismiss notification">
              <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg>
            </button>
          </div>
          <div class="h-0.5 w-full bg-white/10">
            <div class="gt-bar h-full w-full origin-left ${v.bar}" style="transform: scaleX(1); transition-property: transform; transition-timing-function: linear;"></div>
          </div>`;
        region.appendChild(toast);

        // Enter on the next frame so the transition runs
        requestAnimationFrame(() => {
          requestAnimationFrame(() => toast.classList.remove('translate-y-3', 'opacity-0'));
        });

        const bar = toast.querySelector('.gt-bar');
        let remaining = DURATION;
        let startedAt = Date.now();
        let timer = setTimeout(() => dismiss(toast), remaining);

        function runBar(ms) {
          bar.style.transitionDuration = ms + 'ms';
          bar.style.transform = 'scaleX(0)';
        }
        requestAnimationFrame(() => runBar(remaining));

        function pause() {
          clearTimeout(timer);
          remaining = Math.max(0, remaining - (Date.now() - startedAt));
          const ratio = bar.offsetWidth > 0 ? bar.getBoundingClientRect().width / bar.offsetWidth : 0;
          bar.style.transitionDuration = '0ms';
          bar.style.transform = 'scaleX(' + ratio.toFixed(4) + ')';
        }
        function resume() {
          startedAt = Date.now();
          timer = setTimeout(() => dismiss(toast), remaining);
          runBar(remaining);
        }

        toast.querySelector('.gt-close').addEventListener('click', () => { clearTimeout(timer); dismiss(toast); });
        toast.addEventListener('mouseenter', pause);
        toast.addEventListener('mouseleave', resume);
      }

      root.querySelectorAll('[data-gt-trigger]').forEach((btn) => {
        btn.addEventListener('click', () => showGlassToast(btn.dataset.gtTrigger));
      });

      window.showGlassToast = showGlassToast;
    })();
  </script>
</div>
189 lines UTF-8 · LF · Spaces: 2
DevSnips AI ready Claude · Cursor · Windsurf

Agent skill & Model Context Protocol

Pass this component straight into your AI workflow. DevSnips exposes each resource as a structured, addressable registry entry, so your agent installs the real files instead of approximating them.

devsnips://components/toasts/glass-toast
Prompt instruction
I want to use this DevSnips resource in production:

Page:
https://devsnips.site/library/tailwind/components/toasts/glass-toast/

Install: npx devsnips add
Tailwind/Components/Toasts/glass-toast

This is the Glass Toast — Frosted-glass notification toasts in the glassmorphism design language — translucent backdrop-blur panels with semantic glowing accents, a live countdown progress bar, and pause-on-hover, presented over an animated aurora mesh backdrop.

Use this DevSnips resource as the starting point for my project.
Adapt it to my project's stack and conventions, fix any issues,
and make it production-ready while preserving its intended design
and behavior.

Paste into ChatGPT, Claude or your agent — it already carries the page URL and the exact install path.

Resource URI
devsnips://components/toasts/glass-toast