Hero
Hero Sections
You're reading the Button docs because you deserve the best — or you're pretending to. Either way, this component delivers.
TL;DR: Use <Button> when you want something that looks smart, acts fast, and outclasses everything else on the page.
Hero Section One
Using CLI
if you're using twjlabs/ui cli, it should be pretty easy for you
npx @twjlabs/ui add hero-section-onepnpm dlx @twjlabs/ui hero-section-oneManual Installation
if you're not using the cli, you would need to install it manually,
Make sure you have twj-lib folder with necessary utility functions and types in your project. If not, you can refer here to set it up.
Finally,
copy and paste the following code in your components/ui folder
"use client"
import React from 'react';
import { cn } from '@/twj-lib/tw';
import type { Theme } from '@/twj-lib/types';
import { Button } from '@/components/ui/button';
import { fontApplier } from '@/twj-lib/font-applier';
import { useTheme } from '@/contexts/ui-theme-context';
// --- Shared Types ---
interface HeroAction {
label: string;
onClick?: () => void;
}
export interface SharedHeroProps {
heading: string;
subheading: string;
cta1?: HeroAction;
cta2?: HeroAction;
image?: string;
theme?: Theme;
className?: string;
}
export const HeroOne = ({
heading,
subheading,
cta1,
cta2,
image,
theme,
className
}: SharedHeroProps) => {
const {theme: contextTheme} = useTheme()
const [localTheme] = React.useState<Theme>(theme || contextTheme || 'modern');
const themeClass = `theme-${localTheme}`;
const styles = getHeroStyles(localTheme);
const hasImage = !!image;
return (
<section
className={cn(
themeClass,
fontApplier(localTheme),
"relative w-full overflow-hidden pt-20 pb-20 lg:pb-32",
styles.container,
className
)}
>
{/* Background Decorators */}
{localTheme === 'modern' && (
<div className="absolute top-0 right-0 -z-10 h-full w-1/2 bg-gradient-to-bl from-primary/5 to-transparent blur-3xl" />
)}
{localTheme === 'futuristic' && (
<div className="absolute inset-0 -z-10 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px]" />
)}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
<div className={cn(
"flex flex-col lg:flex-row items-center gap-12",
!hasImage && "text-center justify-center"
)}>
{/* Content */}
<div className={cn("flex-1 space-y-8", !hasImage && "max-w-3xl mx-auto")}>
<h1 className={cn("text-4xl sm:text-5xl lg:text-6xl font-extrabold tracking-tight", styles.heading)}>
{heading}
</h1>
<p className={cn("text-lg sm:text-xl max-w-2xl", styles.subheading)}>
{subheading}
</p>
<div className={cn("flex flex-wrap gap-4", !hasImage && "justify-center")}>
{cta1 && (
<Button label={cta1.label} onClick={cta1.onClick} theme={localTheme} variant="primary" size="large" className="w-full sm:w-auto shadow-xl" />
)}
{cta2 && (
<Button label={cta2.label} onClick={cta2.onClick} theme={localTheme} variant={localTheme === 'brutalist' ? 'secondary' : 'outline'} size="large" className="w-full sm:w-auto" />
)}
</div>
</div>
{/* Image */}
{hasImage && (
<div className="flex-1 w-full relative">
<div className={cn("relative rounded-theme overflow-hidden", styles.imageWrapper)}>
<img src={image} alt="Hero Visual" className="w-full h-auto object-cover relative z-10" />
{theme === 'futuristic' && <div className="absolute inset-0 bg-primary/20 blur-3xl -z-10 transform scale-90" />}
{theme === 'brutalist' && <div className="absolute inset-0 bg-black translate-x-3 translate-y-3 -z-10" />}
</div>
</div>
)}
</div>
</div>
</section>
);
};
/* ---------------------------
Shared Theme-based styling
---------------------------- */
function getHeroStyles(theme: Theme) {
switch (theme) {
case 'brutalist':
return {
container: "bg-background border-b-4 border-black",
heading: "text-black uppercase leading-none drop-shadow-[2px_2px_0_rgba(0,0,0,1)]",
subheading: "text-black font-bold mx-auto",
imageWrapper: "border-4 border-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] rounded-none"
};
case 'futuristic':
return {
container: "bg-background text-foreground",
heading: "text-transparent bg-clip-text bg-gradient-to-b from-white to-primary/60 drop-shadow-[0_0_15px_rgba(var(--color-primary),0.3)]",
subheading: "text-muted-foreground",
imageWrapper: "ring-1 ring-primary/50 shadow-[0_0_30px_-5px_var(--color-primary)] bg-black/50 backdrop-blur-sm"
};
case 'elegant':
return {
container: "bg-surface",
heading: "text-foreground font-serif leading-tight",
subheading: "text-muted-foreground italic",
imageWrapper: "shadow-2xl ring-1 ring-black/5 rounded-xl"
};
case 'playful':
return {
container: "bg-surface",
heading: "text-foreground tracking-tight",
subheading: "text-muted-foreground font-medium",
imageWrapper: "rotate-2 border-4 border-white shadow-xl rounded-[2rem]"
};
case 'organic':
return {
container: "bg-[#F5F5F0]",
heading: "text-[#2A2A2A] tracking-tighter",
subheading: "text-[#5A5A5A]",
imageWrapper: "rounded-[3rem] shadow-lg"
};
default: // Modern
return {
container: "bg-surface",
heading: "text-foreground",
subheading: "text-muted-foreground",
imageWrapper: "shadow-2xl rounded-2xl ring-1 ring-black/10"
};
}
}Usage
Import the Button component and use it in your React application like so:
import { Button } from '@/components/ui/button';
<Button variant="primary" size="default">
Primary Button
</Button>Props
The Button component accepts the following custom props:
Prop
Type
Other props are inherited from the native HTML button element.