{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "tabbed-hero-section", "type": "registry:ui", "title": "Tabbed Hero Section", "description": "A SaaS hero section with left-aligned headline, tabbed navigation, app screenshot showcase, and trusted-by logo strip.", "files": [ { "path": "registry/ruixenui/tabbed-hero-section.tsx", "content": "\"use client\";\n\nimport * as React from \"react\";\nimport Link from \"next/link\";\nimport { cn } from \"@/lib/utils\";\n\n/* ── types ───────────────────────────────────────────────────── */\n\ntype Action = { href: string; label: string };\n\ninterface Tab {\n icon?: React.ReactNode;\n label: string;\n}\n\ninterface TrustedBySection {\n description?: React.ReactNode;\n logos: React.ReactNode[];\n}\n\nexport interface TabbedHeroSectionProps {\n /** Main headline — left-aligned */\n title: React.ReactNode;\n /** Subtitle / description text */\n description?: string;\n /** Primary CTA button */\n primaryAction?: Action;\n /** Secondary CTA button */\n secondaryAction?: Action;\n /** Tab buttons shown above the showcase */\n tabs?: Tab[];\n /** Index of the active tab (0-based) */\n activeTab?: number;\n /** Background gradient image for light mode */\n backgroundSrcLight?: string;\n /** Background gradient image for dark mode */\n backgroundSrcDark?: string;\n /** Trusted-by / logo strip section */\n trustedBy?: TrustedBySection;\n className?: string;\n}\n\n/* ── component ───────────────────────────────────────────────── */\n\nexport function TabbedHeroSection({\n title,\n description,\n primaryAction,\n secondaryAction,\n tabs,\n activeTab = 0,\n backgroundSrcLight,\n backgroundSrcDark,\n trustedBy,\n className,\n}: TabbedHeroSectionProps) {\n const [currentTab, setCurrentTab] = React.useState(activeTab);\n\n return (\n \n {/* ── background gradient images ──────────────────── */}\n {(backgroundSrcLight || backgroundSrcDark) && (\n \n {backgroundSrcDark && (\n \n )}\n {backgroundSrcLight && (\n \n )}\n \n )}\n\n
\n {/* ── heading + description + CTAs ────────────────── */}\n
\n

\n {title}\n

\n\n {(description || primaryAction || secondaryAction) && (\n
\n {description && (\n

\n {description}\n

\n )}\n\n {(primaryAction || secondaryAction) && (\n
\n {primaryAction && (\n \n {primaryAction.label}\n \n )}\n {secondaryAction && (\n \n {secondaryAction.label}\n \n )}\n
\n )}\n
\n )}\n
\n\n {/* ── tabbed showcase ────────────────────────────── */}\n {tabs && tabs.length > 0 && (\n
\n \n {tabs.map((tab, idx) => (\n setCurrentTab(idx)}\n className={cn(\n \"flex h-12 cursor-pointer items-center justify-center gap-2 px-3 text-sm transition-colors duration-150 [&>svg]:size-4\",\n idx === currentTab\n ? \"bg-muted text-foreground\"\n : \"text-muted-foreground hover:bg-foreground/5 hover:text-foreground\",\n )}\n >\n {tab.icon}\n {tab.label}\n \n ))}\n
\n
\n
\n )}\n
\n\n {/* ── trusted-by section ──────────────────────────── */}\n {trustedBy && (\n
\n
\n {trustedBy.description && (\n
\n
\n {trustedBy.description}\n
\n
\n )}\n
\n {trustedBy.logos.map((logo, idx) => (\n
\n {logo}\n
\n ))}\n
\n
\n
\n )}\n \n );\n}\n", "type": "registry:ui", "target": "components/ruixen/tabbed-hero-section.tsx" } ] }