Retour au catalogue

Notification Banner

Banniere de notification en haut de page avec CTA, icone et animation de fermeture.

notificationsimple Both Responsive a11y
boldcorporatesaasecommerceuniversalstacked
Theme
"use client";

import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { X, ArrowRight, Megaphone } from "lucide-react";

interface NotificationBannerProps {
  message?: string;
  ctaLabel?: string;
  ctaUrl?: string;
  dismissible?: boolean;
  variant?: "info" | "success" | "warning" | "accent";
}

const ease: [number, number, number, number] = [0.16, 1, 0.3, 1];

export default function NotificationBanner({
  message = "Notification importante",
  ctaLabel = "",
  ctaUrl = "#",
  dismissible = true,
  variant = "accent",
}: NotificationBannerProps) {
  const [visible, setVisible] = useState(true);

  return (
    <AnimatePresence>
      {visible && (
        <motion.div
          initial={{ height: 0, opacity: 0 }}
          animate={{ height: "auto", opacity: 1 }}
          exit={{ height: 0, opacity: 0 }}
          transition={{ duration: 0.3, ease }}
          className="overflow-hidden"
        >
          <div
            className="py-3 px-6"
            style={{
              background: variant === "accent" ? "var(--color-accent)" : "var(--color-background-alt)",
            }}
          >
            <div className="mx-auto max-w-7xl flex items-center justify-center gap-3">
              <Megaphone
                size={16}
                style={{
                  color: variant === "accent" ? "var(--color-background)" : "var(--color-accent)",
                  flexShrink: 0,
                }}
              />
              <p
                className="text-sm font-medium"
                style={{
                  color: variant === "accent" ? "var(--color-background)" : "var(--color-foreground)",
                }}
              >
                {message}
              </p>
              {ctaLabel && (
                <a
                  href={ctaUrl}
                  className="inline-flex items-center gap-1 text-sm font-semibold underline underline-offset-2"
                  style={{
                    color: variant === "accent" ? "var(--color-background)" : "var(--color-accent)",
                  }}
                >
                  {ctaLabel}
                  <ArrowRight size={14} />
                </a>
              )}
              {dismissible && (
                <button
                  onClick={() => setVisible(false)}
                  className="ml-auto flex-shrink-0"
                  style={{
                    color: variant === "accent" ? "var(--color-background)" : "var(--color-foreground-muted)",
                  }}
                >
                  <X size={16} />
                </button>
              )}
            </div>
          </div>
        </motion.div>
      )}
    </AnimatePresence>
  );
}

Avis

Notification Banner — React Notification Section — Incubator