Skip to content

HeroSection

MD · 1950B gzip budget

Full-width hero with heading, subtext, and call-to-action.

Category
Media & layout
Budget
md, several states or a live subscription
External runtime
React / React DOM only
axe fixtureSSR rendersource scanbundle budget

Preview

Live fixture
Preview locale

Welcome

Description

Try the component here. Locale-aware formatting and direction follow the selected language; example content and labels are not automatically translated. Overlay demos use interactive launchers.

Install

npx shadcn@latest add https://gear5-ui.vercel.app/r/hero-section.json

Copies the source into your project.

New here? Set up Tailwind and import aliases first →

Source & props

Edit on GitHub ↗

Prop types and inline documentation are included below. This is repository source; the installer rewrites shared imports for your project.

"use client";

import React from "react";

export interface HeroSectionProps {
  title: string;
  subtitle?: string;
  primaryCta?: { text: string; onClick?: () => void; href?: string };
  secondaryCta?: { text: string; onClick?: () => void; href?: string };
  children?: React.ReactNode;
  className?: string;
  ariaLabel?: string;
}

export function HeroSection({
  title,
  subtitle,
  primaryCta,
  secondaryCta,
  children,
  className = "",
  ariaLabel,
}: HeroSectionProps) {
  return (
    <section
      aria-label={ariaLabel}
      className={className}
      style={{
        width: "100%",
        padding: "4rem 1.5rem",
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        textAlign: "center",
        background: "var(--color-hero-bg, #f9fafb)",
      }}
    >
      <h1
        style={{
          fontSize: "clamp(2rem, 5vw, 3.5rem)",
          fontWeight: 800,
          lineHeight: 1.1,
          marginBlockEnd: "1rem",
          color: "var(--color-text, #111827)",
          maxWidth: "48rem",
        }}
      >
        {title}
      </h1>

      {subtitle && (
        <p
          style={{
            fontSize: "clamp(1rem, 2vw, 1.25rem)",
            lineHeight: 1.6,
            color: "var(--color-muted, #6b7280)",
            maxWidth: "36rem",
            marginBlockEnd: "2rem",
          }}
        >
          {subtitle}
        </p>
      )}

      {(primaryCta || secondaryCta) && (
        <div
          style={{
            display: "flex",
            flexWrap: "wrap",
            gap: "1rem",
            justifyContent: "center",
          }}
        >
          {primaryCta && (
            <a
              href={primaryCta.href}
              onClick={primaryCta.onClick}
              role="button"
              aria-label={primaryCta.text}
              style={{
                display: "inline-flex",
                alignItems: "center",
                padding: "0.75rem 1.5rem",
                borderRadius: "0.5rem",
                background: "var(--color-primary, #3b82f6)",
                color: "#fff",
                fontWeight: 600,
                fontSize: "1rem",
                textDecoration: "none",
                cursor: "pointer",
                transition: "background 0.2s",
              }}
            >
              {primaryCta.text}
            </a>
          )}
          {secondaryCta && (
            <a
              href={secondaryCta.href}
              onClick={secondaryCta.onClick}
              role="button"
              aria-label={secondaryCta.text}
              style={{
                display: "inline-flex",
                alignItems: "center",
                padding: "0.75rem 1.5rem",
                borderRadius: "0.5rem",
                border: "1px solid var(--color-border, #e5e7eb)",
                background: "var(--color-bg, #fff)",
                color: "var(--color-text, #111827)",
                fontWeight: 600,
                fontSize: "1rem",
                textDecoration: "none",
                cursor: "pointer",
                transition: "background 0.2s",
              }}
            >
              {secondaryCta.text}
            </a>
          )}
        </div>
      )}

      {children && (
        <div style={{ marginBlockStart: "2rem", width: "100%", maxWidth: "64rem" }}>
          {children}
        </div>
      )}
    </section>
  );
}

What CI checks

Quality contract
  • Bundled, minified and gzipped against its tier budget
  • Audited by axe in the state previewed above
  • Rendered through react-dom/server with no browser globals
  • Scanned for network calls, dangerous sinks, and unguarded animation