Docs
CTA Banner Simple

CTA Banner Simple

A clean, full-width call-to-action banner with headline, description, and action buttons. Perfect for conversion-focused sections.

Ready to get started?

Join thousands of teams already using our platform to build better products.

Join our community

Connect with thousands of developers building amazing products.

Installation

Copy and paste the following code into your project.

"use client";
 
import { Button } from "@/components/ui/button";
import { ArrowRight } from "lucide-react";
 
interface CTABannerSimpleProps {
  headline: string;
  description?: string;
  variant?: "default" | "primary" | "dark";
  primaryCTA: {
    text: string;
    href?: string;
    onClick?: () => void;
  };
  secondaryCTA?: {
    text: string;
    href?: string;
    onClick?: () => void;
  };
}
 
const variants = {
  default: {
    section: "bg-muted/30",
    headline: "text-foreground",
    description: "text-muted-foreground",
    primaryButton: "",
    secondaryButton: "",
  },
  dark: {
    section: "bg-slate-950",
    headline: "text-white",
    description: "text-slate-400",
    primaryButton: "bg-white text-slate-950 hover:bg-slate-100",
    secondaryButton:
      "border-slate-700 text-white hover:bg-slate-900 hover:text-white",
  },
};
 
export function CTABannerSimple({
  headline,
  description,
  variant = "default",
  primaryCTA,
  secondaryCTA,
}: CTABannerSimpleProps) {
  const styles = variants[variant];
 
  return (
    <section
      className={`relative overflow-hidden py-16 sm:py-20 ${styles.section}`}
    >
      {/* Grid pattern */}
      <div className="absolute inset-0 -z-10 bg-[linear-gradient(to_right,#80808008_1px,transparent_1px),linear-gradient(to_bottom,#80808008_1px,transparent_1px)] bg-[size:24px_24px]" />
 
      <div className="container mx-auto px-6">
        <div className="mx-auto max-w-4xl text-center">
          {/* Headline */}
          <h2
            className={`mb-4 text-3xl font-bold tracking-tight sm:text-4xl md:text-5xl ${styles.headline}`}
          >
            {headline}
          </h2>
 
          {/* Description */}
          {description && (
            <p className={`mb-8 text-lg sm:text-xl ${styles.description}`}>
              {description}
            </p>
          )}
 
          {/* CTAs */}
          <div className="flex flex-col items-center justify-center gap-4 sm:flex-row">
            <Button
              size="lg"
              onClick={primaryCTA.onClick}
              className={`group w-full font-medium sm:w-auto ${styles.primaryButton}`}
            >
              {primaryCTA.text}
              <ArrowRight className="ml-2 h-4 w-4 transition-transform group-hover:translate-x-1" />
            </Button>
 
            {secondaryCTA && (
              <Button
                size="lg"
                variant="outline"
                onClick={secondaryCTA.onClick}
                className={`w-full font-medium sm:w-auto ${styles.secondaryButton}`}
              >
                {secondaryCTA.text}
              </Button>
            )}
          </div>
        </div>
      </div>
    </section>
  );
}

Update the import paths to match your project setup.

import { Button } from "@/components/ui/button";

Features

  • Full-width banner - Spans entire viewport width
  • Theme variants - Default, Primary, and Dark themes
  • Dual CTAs - Primary and optional secondary button
  • Responsive - Stacks on mobile, inline on desktop
  • Customizable - All text and actions configurable
  • Accessible - Keyboard navigation and semantic HTML
  • TypeScript support - Full type safety
  • Production-ready - Copy and paste to use

Usage

Basic Usage

import CTABannerSimple from "@/components/ui/cta-banner-simple";
 
export default function Page() {
  return (
    <CTABannerSimple
      headline="Ready to get started?"
      description="Join thousands of teams already using our platform."
      primaryCTA={{
        text: "Start Free Trial",
        onClick: () => console.log("CTA clicked"),
      }}
    />
  );
}

Theme Variants

{/* Default - Subtle muted background */}
<CTABannerSimple
  variant="default"
  headline="Ready to get started?"
  primaryCTA={{ text: "Get Started", onClick: () => {} }}
/>
 
{/* Primary - Full brand color background */}
<CTABannerSimple
  variant="primary"
  headline="Ready to get started?"
  primaryCTA={{ text: "Get Started", onClick: () => {} }}
/>
 
{/* Dark - Deep dark theme with white text */}
<CTABannerSimple
  variant="dark"
  headline="Ready to get started?"
  primaryCTA={{ text: "Get Started", onClick: () => {} }}
/>

With Secondary CTA

<CTABannerSimple
  headline="Ready to get started?"
  description="Join thousands of teams already using our platform."
  primaryCTA={{
    text: "Start Free Trial",
    onClick: () => {},
  }}
  secondaryCTA={{
    text: "Contact Sales",
    onClick: () => {},
  }}
/>

With Router Navigation

"use client";
 
import { useRouter } from "next/navigation";
import CTABannerSimple from "@/components/ui/cta-banner-simple";
 
export default function Page() {
  const router = useRouter();
 
  return (
    <CTABannerSimple
      headline="Ready to transform your workflow?"
      description="Start your 14-day free trial today. No credit card required."
      primaryCTA={{
        text: "Get Started",
        onClick: () => router.push("/signup"),
      }}
      secondaryCTA={{
        text: "Learn More",
        onClick: () => router.push("/features"),
      }}
    />
  );
}

Minimal Version

<CTABannerSimple
  headline="Start building today"
  primaryCTA={{
    text: "Get Started",
    onClick: () => {},
  }}
/>

Props

PropTypeDefaultDescription
headlinestringRequiredMain CTA headline
descriptionstringundefinedOptional description text
variant"default" | "primary" | "dark""default"Theme variant
primaryCTAobjectRequiredPrimary button configuration
primaryCTA.textstringRequiredButton text
primaryCTA.hrefstringundefinedOptional link URL
primaryCTA.onClick() => voidundefinedOptional click handler
secondaryCTAobjectundefinedOptional secondary button
secondaryCTA.textstringRequiredButton text
secondaryCTA.hrefstringundefinedOptional link URL
secondaryCTA.onClick() => voidundefinedOptional click handler

TypeScript Interface

interface CTABannerSimpleProps {
  headline: string;
  description?: string;
  variant?: "default" | "primary" | "dark";
  primaryCTA: {
    text: string;
    href?: string;
    onClick?: () => void;
  };
  secondaryCTA?: {
    text: string;
    href?: string;
    onClick?: () => void;
  };
}

Change Button Styles

<Button
  size="lg"
  className="bg-gradient-to-r from-primary to-primary/80"
>
  {primaryCTA.text}
</Button>

Add Icons

import { Rocket, MessageCircle } from "lucide-react";
 
<Button>
  <Rocket className="mr-2 h-4 w-4" />
  {primaryCTA.text}
</Button>

Center Align Buttons

<div className="flex items-center justify-center gap-4">
  {/* buttons */}
</div>

Use Cases

Perfect for:

  • Bottom of landing pages
  • End of blog posts
  • Between content sections
  • Product pages
  • Documentation pages
  • Pricing pages
  • Feature pages
  • About pages

Best Practices

  1. Keep it simple - One clear message and action
  2. Action-oriented - Use verbs in button text
  3. Create urgency - "Start today", "Get started now"
  4. Remove friction - "No credit card required"
  5. Contrast - Make buttons stand out
  6. Mobile-first - Test on small screens
  7. A/B test - Try different copy and layouts