Everything you need to succeed
Features
- ✅ Professional design - Clean cards with elegant spacing
- ✅ Gradient icons - Beautiful gradient backgrounds for all icons
- ✅ Optional metrics - Show growth stats (e.g., "+127%")
- ✅ Feature badges - "Popular", "New", "Enterprise" labels
- ✅ Interactive links - "Learn more" links with hover effects
- ✅ Hover animations - Icon scales, card lifts, gradient reveals
- ✅ Bottom CTA card - Professional call-to-action section
- ✅ Responsive grid - 4 columns → 2 columns → 1 column
- ✅ Shadcn components - Built with Card, Badge, Button
- ✅ TypeScript support - Full type safety
- ✅ Production-ready - Copy and paste to use
Installation
Copy and paste the following code into your project.
"use client";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { ArrowRight, LucideIcon, Sparkles, TrendingUp } from "lucide-react";
interface Feature {
icon: LucideIcon;
title: string;
description: string;
link?: {
text: string;
href?: string;
onClick?: () => void;
};
badge?: string;
metric?: string;
}
interface FeatureGrid4ColProps {
badge?: string;
headline: string;
description?: string;
features: Feature[];
cta?: {
text: string;
href?: string;
onClick?: () => void;
};
}
export function FeatureGrid4Col({
badge,
headline,
description,
features,
cta,
}: FeatureGrid4ColProps) {
const colors = [
{ gradient: "from-orange-500 to-amber-500", light: "bg-orange-500/10" },
{ gradient: "from-blue-500 to-cyan-500", light: "bg-blue-500/10" },
{ gradient: "from-purple-500 to-pink-500", light: "bg-purple-500/10" },
{ gradient: "from-green-500 to-emerald-500", light: "bg-green-500/10" },
{ gradient: "from-red-500 to-rose-500", light: "bg-red-500/10" },
{ gradient: "from-indigo-500 to-violet-500", light: "bg-indigo-500/10" },
{ gradient: "from-yellow-500 to-orange-500", light: "bg-yellow-500/10" },
{ gradient: "from-teal-500 to-cyan-500", light: "bg-teal-500/10" },
];
return (
<section className="relative overflow-hidden py-24 sm:py-32">
<div className="absolute inset-0 -z-10 bg-gradient-to-b from-background via-background to-muted/30" />
<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:40px_40px]" />
<div className="absolute inset-0 -z-10 overflow-hidden">
<div className="absolute left-[15%] top-[10%] h-[500px] w-[500px] rounded-full bg-gradient-to-br from-primary/10 to-transparent blur-3xl" />
<div className="absolute right-[15%] bottom-[10%] h-[400px] w-[400px] rounded-full bg-gradient-to-tl from-purple-500/10 to-transparent blur-3xl" />
</div>
<div className="container mx-auto px-6">
<div className="mx-auto mb-16 max-w-3xl text-center">
{badge && (
<div className="mb-6 inline-flex animate-in fade-in slide-in-from-bottom-3 duration-700">
<Badge
variant="outline"
className="border-primary/20 bg-primary/10 px-4 py-1.5 text-sm font-medium text-primary backdrop-blur-sm"
>
<Sparkles className="mr-2 h-3.5 w-3.5" />
{badge}
</Badge>
</div>
)}
<h2 className="mb-6 animate-in fade-in slide-in-from-bottom-4 text-4xl font-bold tracking-tight duration-1000 sm:text-5xl md:text-6xl">
{headline}
</h2>
{description && (
<p className="animate-in fade-in slide-in-from-bottom-5 text-lg leading-relaxed text-muted-foreground duration-1000 sm:text-xl">
{description}
</p>
)}
</div>
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
{features.map((feature, index) => {
const Icon = feature.icon;
const color = colors[index % colors.length];
return (
<div
key={index}
className="group animate-in fade-in slide-in-from-bottom-6 duration-1000"
style={{ animationDelay: `${index * 100}ms` }}
>
<Card className="relative h-full overflow-hidden border-border/50 bg-card/50 p-6 backdrop-blur-sm transition-all duration-300 hover:border-border hover:bg-card hover:shadow-xl">
{feature.badge && (
<div className="mb-4">
<Badge
variant="secondary"
className="bg-primary/10 text-xs font-medium text-primary"
>
{feature.badge}
</Badge>
</div>
)}
<div className="mb-5 flex items-center justify-between">
<div
className={`inline-flex rounded-xl bg-gradient-to-br ${color.gradient} p-3 shadow-lg transition-all duration-300 group-hover:scale-110 group-hover:shadow-xl`}
>
<Icon className="h-6 w-6 text-white" />
</div>
{feature.metric && (
<div className="flex items-center gap-1 text-xs font-semibold text-green-600 dark:text-green-400">
<TrendingUp className="h-3.5 w-3.5" />
{feature.metric}
</div>
)}
</div>
<h3 className="mb-3 text-xl font-semibold leading-tight">
{feature.title}
</h3>
<p className="mb-4 text-sm leading-relaxed text-muted-foreground">
{feature.description}
</p>
{feature.link && (
<button
onClick={feature.link.onClick}
className="group/link inline-flex items-center gap-1 text-sm font-medium text-primary transition-all hover:gap-2"
>
{feature.link.text}
<ArrowRight className="h-3.5 w-3.5 transition-transform group-hover/link:translate-x-0.5" />
</button>
)}
<div
className={`absolute -right-8 -top-8 h-24 w-24 rounded-full ${color.light} opacity-0 blur-2xl transition-opacity duration-500 group-hover:opacity-100`}
/>
<div
className={`absolute inset-x-0 bottom-0 h-1 w-0 bg-gradient-to-r ${color.gradient} transition-all duration-500 group-hover:w-full`}
/>
</Card>
</div>
);
})}
</div>
{cta && (
<div className="mt-20 animate-in fade-in slide-in-from-bottom-8 text-center duration-1000">
<Card className="inline-flex flex-col items-center gap-6 border-border/50 bg-card/50 p-10 backdrop-blur-sm">
<div className="space-y-3 text-center">
<h3 className="text-2xl font-bold">Ready to get started?</h3>
<p className="max-w-md text-muted-foreground">
Join thousands of teams already using our platform to build
better products
</p>
</div>
<Button
size="lg"
onClick={cta.onClick}
className="group h-12 bg-gradient-to-r from-primary to-primary/80 px-8 text-base font-semibold shadow-lg transition-all hover:scale-105 hover:shadow-xl"
>
{cta.text}
<ArrowRight className="ml-2 h-4 w-4 transition-transform group-hover:translate-x-1" />
</Button>
</Card>
</div>
)}
</div>
</section>
);
}Update the import paths to match your project setup.
Usage
Basic Usage
import FeatureGrid4Col from "@/components/ui/feature-grid-4col";
import { Zap, Shield, Sparkles, Rocket } from "lucide-react";
export default function FeaturesPage() {
return (
<FeatureGrid4Col
headline="Everything you need"
features={[
{
icon: Zap,
title: "Lightning Fast",
description: "Optimized for speed and performance.",
},
{
icon: Shield,
title: "Secure",
description: "Enterprise-grade security built-in.",
},
{
icon: Sparkles,
title: "AI-Powered",
description: "Leverage cutting-edge AI technology.",
},
{
icon: Rocket,
title: "Deploy Instantly",
description: "Push to production in seconds.",
},
]}
/>
);
}With All Features
import FeatureGrid4Col from "@/components/ui/feature-grid-4col";
import { Zap, Shield, Sparkles, Rocket } from "lucide-react";
export default function FeaturesPage() {
return (
<FeatureGrid4Col
badge="Platform Features"
headline="Built for modern teams"
description="Everything you need to build, deploy, and scale your applications."
features={[
{
icon: Zap,
title: "Lightning Fast",
description: "Optimized for speed with edge computing and global CDN.",
badge: "Popular",
metric: "+127%",
link: {
text: "Learn more",
onClick: () => console.log("Clicked"),
},
},
{
icon: Shield,
title: "Secure by Default",
description: "Enterprise-grade security with SOC 2 compliance.",
badge: "Enterprise",
link: {
text: "View security",
onClick: () => console.log("Clicked"),
},
},
// ... more features
]}
cta={{
text: "View All Features",
onClick: () => console.log("CTA clicked"),
}}
/>
);
}With Router Navigation
"use client";
import { useRouter } from "next/navigation";
import FeatureGrid4Col from "@/components/ui/feature-grid-4col";
export default function FeaturesPage() {
const router = useRouter();
return (
<FeatureGrid4Col
headline="Powerful features"
features={[
{
icon: Zap,
title: "Fast Performance",
description: "Lightning-fast load times.",
link: {
text: "Learn more",
onClick: () => router.push("/features/performance"),
},
},
]}
cta={{
text: "Get Started",
onClick: () => router.push("/signup"),
}}
/>
);
}Props
FeatureGrid4ColProps
| Prop | Type | Default | Description |
|---|---|---|---|
badge | string | undefined | Optional badge text above headline |
headline | string | Required | Main section headline |
description | string | undefined | Optional description below headline |
features | Feature[] | Required | Array of feature objects |
cta | object | undefined | Optional bottom CTA section |
cta.text | string | Required | CTA button text |
cta.href | string | Optional | Link URL |
cta.onClick | () => void | Optional | Click handler |
Feature Object
| Prop | Type | Description |
|---|---|---|
icon | LucideIcon | Icon component from lucide-react |
title | string | Feature title |
description | string | Feature description |
badge | string | Optional badge (e.g., "Popular", "New") |
metric | string | Optional metric (e.g., "+127%", "10x faster") |
link | object | Optional link object |
link.text | string | Link text |
link.href | string | Optional link URL |
link.onClick | () => void | Optional click handler |
TypeScript Interface
import { LucideIcon } from "lucide-react";
interface Feature {
icon: LucideIcon;
title: string;
description: string;
link?: {
text: string;
href?: string;
onClick?: () => void;
};
badge?: string;
metric?: string;
}
interface FeatureGrid4ColProps {
badge?: string;
headline: string;
description?: string;
features: Feature[];
cta?: {
text: string;
href?: string;
onClick?: () => void;
};
}Customization
Change Grid Columns
Adjust the grid layout:
{/* 3 columns on desktop */}
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
{/* 5 columns on desktop */}
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-5">Customize Colors
The component uses 8 predefined gradient colors. To customize:
const colors = [
{ gradient: "from-red-500 to-rose-500", light: "bg-red-500/10" },
{ gradient: "from-green-500 to-emerald-500", light: "bg-green-500/10" },
// Add more colors...
];Modify Card Style
<Card className="rounded-2xl border-2 p-8 hover:shadow-2xl">
{/* content */}
</Card>Hide CTA Section
Simply omit the cta prop:
<FeatureGrid4Col
headline="Features"
features={[/* ... */]}
// No cta prop
/>Use Cases
Perfect for:
- Product feature pages
- SaaS platform capabilities
- Service offerings
- Tool comparisons
- Benefits sections
- Technology showcases
- Integration displays
- API features
Best Practices
- Optimal feature count - 8-12 features work best for 4-column layout
- Use metrics wisely - Only add metrics where relevant (growth, speed, etc.)
- Badge sparingly - Highlight 2-3 key features with badges
- Consistent descriptions - Keep similar length (1-2 sentences)
- Relevant icons - Choose icons that clearly represent the feature
- Test interactions - Ensure all links and CTAs work properly
- Mobile optimization - Test on mobile devices