heroes /
Announcement Bar + Hero
Dismissable promo banner strip at the top (with localStorage persistence) paired with a centered hero section below.
Preview
Source
tsx
"use client";
import { useState, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { X, ArrowRight, Megaphone } from "lucide-react";
import { Button } from "@/components/ui/button";
const STORAGE_KEY = "announcement-bar-dismissed-v1";
export default function AnnouncementBarHero() {
const [bannerVisible, setBannerVisible] = useState(false);
useEffect(() => {
// Guard localStorage in useEffect for SSR safety
const dismissed = localStorage.getItem(STORAGE_KEY);
if (!dismissed) {
setBannerVisible(true);
}
}, []);
const dismiss = () => {
setBannerVisible(false);
try {
localStorage.setItem(STORAGE_KEY, "1");
} catch {
// localStorage not available (private mode, etc.)
}
};
return (
<div className="flex flex-col">
{/* Announcement Banner */}
<AnimatePresence>
{bannerVisible && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="overflow-hidden"
>
<div className="bg-gradient-to-r from-primary via-violet-600 to-fuchsia-600 text-white">
<div className="container mx-auto px-4 py-2.5 flex items-center justify-between gap-4">
<div className="flex items-center gap-2 text-sm font-medium flex-1 justify-center">
<Megaphone className="w-4 h-4 shrink-0" />
<span>
<strong>Black Friday deal:</strong> 40% off all plans through
Dec 1st.
</span>
<a
href="#"
className="underline underline-offset-2 font-semibold hover:no-underline ml-1 hidden sm:inline"
>
Claim offer →
</a>
</div>
<button
onClick={dismiss}
aria-label="Dismiss announcement"
className="shrink-0 rounded-full p-1 hover:bg-white/20 transition-colors"
>
<X className="w-4 h-4" />
</button>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
{/* Hero Section */}
<section className="relative min-h-screen flex items-center justify-center overflow-hidden bg-background">
{/* Background decoration */}
<div className="absolute inset-0 pointer-events-none">
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[900px] h-[600px] bg-gradient-to-b from-primary/8 to-transparent rounded-full blur-3xl" />
</div>
<div className="relative z-10 container mx-auto px-6 text-center max-w-3xl">
<motion.div
initial={{ opacity: 0, y: 40 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, ease: "easeOut" }}
className="flex flex-col items-center gap-6"
>
<span className="inline-flex items-center gap-2 text-xs font-semibold uppercase tracking-widest text-primary bg-primary/10 border border-primary/20 rounded-full px-4 py-2">
Limited time offer active
</span>
<h1 className="text-5xl sm:text-6xl lg:text-7xl font-extrabold tracking-tight text-foreground leading-[1.05]">
Launch your next
<br />
<span className="bg-gradient-to-r from-primary to-fuchsia-500 bg-clip-text text-transparent">
big thing
</span>
</h1>
<p className="text-lg sm:text-xl text-muted-foreground max-w-xl leading-relaxed">
Everything you need to go from idea to live product in record time.
Beautifully designed, obsessively optimized.
</p>
<div className="flex flex-col sm:flex-row items-center gap-3 pt-2">
<Button size="lg" className="gap-2 text-base">
Get 40% off today
<ArrowRight className="w-4 h-4" />
</Button>
<Button size="lg" variant="outline" className="text-base">
Learn more
</Button>
</div>
<p className="text-sm text-muted-foreground">
Offer expires Dec 1st · No credit card required
</p>
</motion.div>
</div>
</section>
</div>
);
} Claude Code Instructions
CLI Install
npx innovations add announcement-barWhere to use it
IMPORTANT: Place this ABOVE your main navbar — it should be the very first element in your page layout.
In Astro layout (src/layouts/Layout.astro):
import AnnouncementBarHero from '../components/innovations/heroes/announcement-bar';
// Add before <slot /> or <Header /> in your layout body
In Next.js root layout (app/layout.tsx):
import AnnouncementBarHero from '@/components/innovations/heroes/announcement-bar';
// Place before the <main> tag and navbar in your layout
Customize the banner message and colors via the gradient classes on the banner div. Change STORAGE_KEY if you update the banner content (this ensures returning users see the new message). The hero section below can be swapped for any other hero component.