Snackbar

Overlay & Feedback

Brief message bar with optional action button.

Preview

Usage

example.jsx
import { Snackbar } from "@/components/ui/snackbar";

export default function Example() {
  return <Snackbar />;
}

Source Code

Copy this file into components/ui/snackbar.jsx in your project.

snackbar.jsx
"use client";

import { forwardRef, useState, useEffect } from "react";
import { cn } from "@/lib/utils";

const Snackbar = forwardRef(({ className, open, onClose, message, action, duration = 5000, ...props }, ref) => {
  useEffect(() => {
    if (open && duration) {
      const timer = setTimeout(() => onClose?.(), duration);
      return () => clearTimeout(timer);
    }
  }, [open, duration, onClose]);

  if (!open) return null;
  return (
    <div ref={ref} className={cn("fixed bottom-4 left-1/2 z-50 flex -translate-x-1/2 items-center gap-4 rounded-lg bg-foreground px-4 py-3 text-sm text-background shadow-lg animate-in slide-in-from-bottom-4", className)} {...props}>
      <span>{message}</span>
      {action && <button onClick={action.onClick} className="shrink-0 font-medium text-primary-foreground underline">{action.label}</button>}
      <button onClick={onClose} className="shrink-0 opacity-70 hover:opacity-100">
        <svg className="h-4 w-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>
  );
});
Snackbar.displayName = "Snackbar";

export { Snackbar };

Quick Install

Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.

npm install clsx tailwind-merge