Everything you need to succeed
Powerful features designed to help your business grow
Lightning Fast
Experience blazing-fast performance with our optimized infrastructure and global CDN network.
Enterprise Security
Bank-level security with end-to-end encryption, compliance certifications, and advanced threat protection.
Advanced Analytics
Get deep insights with real-time analytics, custom dashboards, and predictive intelligence.
Team Collaboration
Work together seamlessly with real-time collaboration, comments, and team management tools.
Global Infrastructure
Deploy worldwide with our multi-region infrastructure and intelligent routing for optimal performance.
Mobile First
Native mobile experience with offline support, push notifications, and cross-platform SDKs.
Privacy Focused
GDPR compliant with data anonymization, user consent management, and privacy-first design.
Infinite Scale
Scale from zero to millions of users without breaking a sweat with our auto-scaling architecture.
Developer Friendly
Comprehensive REST & GraphQL APIs with SDKs, webhooks, and extensive documentation.
Want to see all features in action?
Request a DemoInstallation
Install dependencies
npm install framer-motionCopy and paste the following code into your project.
"use client";
import { useState, createElement } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { ArrowRight, Check } from "lucide-react";
interface Feature {
id: string;
title: string;
description: string;
icon: React.ElementType;
color: string;
benefits?: string[];
stats?: {
label: string;
value: string;
};
ctaText?: string;
ctaLink?: string;
image?: string;
}
interface FeatureCardsHoverProps {
title?: string;
description?: string;
features: Feature[];
className?: string;
}
export function FeatureCardsHover({
title = "Everything you need to succeed",
description = "Powerful features designed to help your business grow",
features,
className = "",
}: FeatureCardsHoverProps) {
const [hoveredCard, setHoveredCard] = useState<string | null>(null);
return (
<section className={`w-full bg-white py-20 dark:bg-black ${className}`}>
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="mb-16 text-center">
<h2 className="mb-4 text-4xl font-bold text-zinc-900 dark:text-white sm:text-5xl">
{title}
</h2>
<p className="mx-auto max-w-2xl text-lg text-zinc-600 dark:text-zinc-400">
{description}
</p>
</div>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{features.map((feature, index) => {
const Icon = feature.icon;
const isHovered = hoveredCard === feature.id;
return (
<motion.div
key={feature.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
onMouseEnter={() => setHoveredCard(feature.id)}
onMouseLeave={() => setHoveredCard(null)}
className="group relative overflow-hidden rounded-2xl border-2 border-zinc-200 bg-white transition-all duration-300 hover:shadow-lg dark:border-zinc-800 dark:bg-zinc-950"
style={
isHovered
? {
borderColor: feature.color,
boxShadow: `0 0 0 1px ${feature.color}20`,
}
: {}
}
>
<div
className="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-500 group-hover:opacity-20"
style={{
background: `radial-gradient(circle at 50% 0%, ${feature.color}, transparent 70%)`,
}}
/>
<div className="relative h-full p-8">
<div className="mb-6">
<motion.div
className={`mb-6 inline-flex h-14 w-14 items-center justify-center rounded-xl transition-all duration-300 ${
!isHovered ? "bg-zinc-100 dark:bg-zinc-900" : ""
}`}
style={
isHovered
? {
backgroundColor: feature.color,
boxShadow: `0 0 30px ${feature.color}40`,
}
: {}
}
animate={{
scale: isHovered ? 1.1 : 1,
rotate: isHovered ? 5 : 0,
}}
transition={{ duration: 0.3, ease: "easeOut" }}
>
{createElement(Icon, {
className: isHovered
? "h-7 w-7 text-white transition-colors duration-300"
: "h-7 w-7 text-zinc-600 transition-colors duration-300 dark:text-zinc-400",
})}
</motion.div>
<h3 className="mb-3 text-xl font-bold text-zinc-900 dark:text-white">
{feature.title}
</h3>
<p className="leading-relaxed text-zinc-600 dark:text-zinc-400">
{feature.description}
</p>
</div>
<AnimatePresence initial={false}>
{isHovered && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="overflow-hidden"
>
{feature.benefits && feature.benefits.length > 0 && (
<div className="mb-6 space-y-3">
{feature.benefits.map((benefit, idx) => (
<motion.div
key={idx}
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: idx * 0.1 }}
className="flex items-start gap-3"
>
<div
className="mt-1 flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full"
style={{
backgroundColor: `${feature.color}20`,
}}
>
<Check
className="h-3 w-3"
style={{ color: feature.color }}
/>
</div>
<span className="text-sm text-zinc-700 dark:text-zinc-300">
{benefit}
</span>
</motion.div>
))}
</div>
)}
{feature.stats && (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="mb-6 rounded-lg border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-900/50"
>
<div
className="text-2xl font-bold"
style={{ color: feature.color }}
>
{feature.stats.value}
</div>
<div className="text-sm text-zinc-600 dark:text-zinc-400">
{feature.stats.label}
</div>
</motion.div>
)}
<motion.a
href={feature.ctaLink || "#"}
initial={{ opacity: 1, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="group/cta flex items-center justify-between rounded-lg border border-zinc-300 bg-zinc-100 px-4 py-3 transition-all duration-300 hover:border-zinc-400 hover:bg-zinc-200 dark:border-zinc-700 dark:bg-zinc-900 dark:hover:border-zinc-600 dark:hover:bg-zinc-800"
style={
isHovered ? { borderColor: feature.color } : {}
}
>
<span className="font-semibold text-zinc-900 dark:text-white">
{feature.ctaText || "Learn More"}
</span>
<ArrowRight className="h-4 w-4 text-zinc-600 transition-transform duration-300 group-hover/cta:translate-x-1 dark:text-zinc-400" />
</motion.a>
</motion.div>
)}
</AnimatePresence>
</div>
{/* Corner Accent */}
<div
className="pointer-events-none absolute right-0 top-0 h-20 w-20 opacity-0 transition-opacity duration-500 group-hover:opacity-100"
style={{
background: `radial-gradient(circle at 100% 0%, ${feature.color}40, transparent 70%)`,
}}
/>
</motion.div>
);
})}
</div>
{/* Bottom CTA */}
<div className="mt-16 text-center">
<p className="mb-6 text-zinc-600 dark:text-zinc-400">
Want to see all features in action?
</p>
<motion.a
href="#demo"
className="inline-flex items-center gap-2 rounded-lg bg-zinc-900 px-8 py-4 font-semibold text-white transition-all duration-300 hover:bg-zinc-800 dark:bg-white dark:text-black dark:hover:bg-zinc-100"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
<span>Request a Demo</span>
<ArrowRight className="h-5 w-5" />
</motion.a>
</div>
</div>
</section>
);
}Update the import paths to match your project setup.
Features
- ✅ Hover reveal - Additional content appears smoothly on hover
- ✅ Animated icons - Icons scale and rotate on hover
- ✅ Benefits list - Show key benefits with checkmarks
- ✅ Stats display - Highlight important metrics
- ✅ CTA buttons - Call-to-action with hover effects
- ✅ Color themes - Each card has its own color
- ✅ Gradient effects - Background and corner accents
- ✅ Border animations - Colored borders on hover
- ✅ Responsive grid - 1-3 columns based on screen size
- ✅ TypeScript support - Full type safety
Usage
Basic Usage
import FeatureCardsHover from "@/components/ui/feature-cards-hover";
import {Zap, Shield, BarChart3} from "lucide-react";
const features = [
{
id: "performance",
title: "Lightning Fast",
description: "Experience blazing-fast performance",
icon: Zap,
color: "#f59e0b",
benefits: [
"Sub-50ms response times",
"Auto-scaling infrastructure",
"Edge caching",
],
stats: {
label: "Response Time",
value: "<50ms",
},
ctaText: "Learn More",
ctaLink: "/performance",
},
// ... more features
];
export default function Page() {
return <FeatureCardsHover features={features} />;
}With Custom Title
<FeatureCardsHover
title="Why Choose Us"
description="Features that set us apart from the competition"
features={features}
/>Minimal Cards (No Hover Content)
const features = [
{
id: "simple",
title: "Simple Feature",
description: "Just title and description",
icon: Zap,
color: "#3b82f6",
// No benefits, stats, or CTA
},
];Props
FeatureCardsHoverProps
| Prop | Type | Default | Description |
|---|---|---|---|
features | Feature[] | Required | Array of feature objects |
title | string | "Everything you need..." | Section title |
description | string | "Powerful features..." | Section description |
className | string | "" | Additional CSS classes |
Feature
| Prop | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier |
title | string | Yes | Feature title |
description | string | Yes | Feature description |
icon | React.ElementType | Yes | Lucide icon component |
color | string | Yes | Hex color code |
benefits | string[] | No | List of benefits (shown on hover) |
stats | Stat | No | Stat object (shown on hover) |
ctaText | string | No | CTA button text |
ctaLink | string | No | CTA button link |
image | string | No | Feature image URL |
Stat
| Prop | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Stat label |
value | string | Yes | Stat value |
TypeScript Interface
interface Feature {
id: string;
title: string;
description: string;
icon: React.ElementType;
color: string;
benefits?: string[];
stats?: {
label: string;
value: string;
};
ctaText?: string;
ctaLink?: string;
image?: string;
}
interface FeatureCardsHoverProps {
title?: string;
description?: string;
features: Feature[];
className?: string;
}Use Cases
Perfect for:
- SaaS product features
- Service offerings
- Platform capabilities
- Tool highlights
- Benefit showcases
- Feature comparisons
- Product tours
- Landing pages
Customization
Change Hover Animation Speed
// In the AnimatePresence section
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.5 }} // Change from 0.3 to 0.5
>Always Show Benefits (No Hover)
// Remove AnimatePresence and conditional rendering
<div className="mb-6 space-y-3">
{feature.benefits?.map((benefit, idx) => (
// ... benefit content
))}
</div>Add Feature Images
// Add before the icon section
{
feature.image && (
<img
src={feature.image}
alt={feature.title}
className="mb-4 h-40 w-full rounded-lg object-cover"
/>
);
}Change Grid Columns
// Modify the grid classes
className = "grid gap-6 md:grid-cols-2 xl:grid-cols-4"; // 4 columns on xlRemove Stats
// Simply don't include stats property in feature objects
const features = [
{
id: "feature",
title: "Feature",
description: "Description",
icon: Zap,
color: "#3b82f6",
benefits: ["Benefit 1", "Benefit 2"],
// No stats property
},
];Custom Hover Trigger
// Change hover trigger to click
onClick={() => setHoveredCard(hoveredCard === feature.id ? null : feature.id)}
// Remove onHoverStart and onHoverEndAccessibility
- Keyboard navigation - Cards are focusable
- Screen readers - Semantic HTML structure
- Color contrast - WCAG AA compliant
- Motion - Respects prefers-reduced-motion
- Focus states - Visible focus indicators
Performance
- Lazy animations - Only animates visible cards
- GPU acceleration - Uses transform and opacity
- Optimized re-renders - Minimal state updates
- Efficient hover - Single state for all cards