BentoGrid.tsx
Modern grid layout component for showcasing features with interactive cards
The Bento Grid component creates a modern, Pinterest-style grid layout with interactive cards that reveal call-to-action buttons on hover.
Features
- Responsive grid layout
- Interactive hover effects
- Background media support
- Icon integration with SvgFinder
- Smooth animations
- Customizable card sizes
Basic Usage
import { BentoGrid, BentoCard } from '@/components/ui/BentoGrid';
export default function Page() {
return (
<BentoGrid>
<BentoCard
name="Feature 1"
className="col-span-3 lg:col-span-1"
background={<div className="absolute inset-0 bg-gradient-to-br from-brand/20 to-brand/5" />}
icon="lockIcon"
description="Secure authentication with Clerk"
href="/docs/core/authentication"
cta="Learn more"
/>
<BentoCard
name="Feature 2"
className="col-span-3 lg:col-span-2"
background={<div className="absolute inset-0 bg-gradient-to-br from-purple-500/20 to-purple-500/5" />}
icon="walletIcon"
description="Accept payments with Stripe"
href="/docs/core/payments"
cta="Get started"
/>
</BentoGrid>
);
}With Images
import { BentoGrid, BentoCard } from '@/components/ui/BentoGrid';
import Image from 'next/image';
<BentoGrid>
<BentoCard
name="Dashboard"
className="col-span-3 lg:col-span-2"
background={
<Image
src="/screenshots/dashboard.png"
alt="Dashboard"
fill
className="object-cover opacity-60"
/>
}
icon="chartIcon"
description="Powerful analytics dashboard"
href="/dashboard"
cta="View dashboard"
/>
</BentoGrid>Custom Grid Layout
<BentoGrid className="grid-cols-1 md:grid-cols-2 lg:grid-cols-4">
<BentoCard
name="Small Card"
className="col-span-1"
background={<div className="bg-blue-500/10" />}
icon="starIcon"
description="Small feature card"
href="/feature-1"
cta="Explore"
/>
<BentoCard
name="Wide Card"
className="col-span-1 md:col-span-2"
background={<div className="bg-green-500/10" />}
icon="rocketIcon"
description="Wide feature card"
href="/feature-2"
cta="Discover"
/>
<BentoCard
name="Tall Card"
className="col-span-1 row-span-2"
background={<div className="bg-purple-500/10" />}
icon="zap Icon"
description="Tall feature card"
href="/feature-3"
cta="Learn more"
/>
</BentoGrid>With Video Background
<BentoCard
name="Video Demo"
className="col-span-3"
background={
<video
autoPlay
loop
muted
playsInline
className="absolute inset-0 w-full h-full object-cover opacity-50"
>
<source src="/videos/demo.mp4" type="video/mp4" />
</video>
}
icon="playIcon"
description="Watch our product in action"
href="/demo"
cta="Watch demo"
/>Feature Showcase
import { BentoGrid, BentoCard } from '@/components/ui/BentoGrid';
export default function Features() {
const features = [
{
name: 'Authentication',
icon: 'lockIcon',
description: 'Secure user authentication with Clerk',
href: '/docs/core/authentication',
cta: 'Learn more',
background: <div className="bg-gradient-to-br from-blue-500/20 to-blue-500/5" />,
className: 'col-span-3 lg:col-span-1',
},
{
name: 'Payments',
icon: 'walletIcon',
description: 'Accept payments with Stripe integration',
href: '/docs/core/payments',
cta: 'Get started',
background: <div className="bg-gradient-to-br from-green-500/20 to-green-500/5" />,
className: 'col-span-3 lg:col-span-2',
},
{
name: 'Database',
icon: 'databaseIcon',
description: 'PostgreSQL with Prisma ORM',
href: '/docs/core/database',
cta: 'Explore',
background: <div className="bg-gradient-to-br from-purple-500/20 to-purple-500/5" />,
className: 'col-span-3 lg:col-span-2',
},
{
name: 'Email',
icon: 'emailIcon',
description: 'Transactional emails with Resend',
href: '/docs/core/emails',
cta: 'View docs',
background: <div className="bg-gradient-to-br from-orange-500/20 to-orange-500/5" />,
className: 'col-span-3 lg:col-span-1',
},
];
return (
<BentoGrid>
{features.map((feature) => (
<BentoCard key={feature.name} {...feature} />
))}
</BentoGrid>
);
}Implementation
The BentoCard includes hover animations:
const BentoCard = ({
name,
className,
background,
icon,
description,
href,
cta,
}: IBentoCardProps) => (
<div
className={cn(
'group relative flex flex-col justify-between overflow-hidden rounded-xl bg-surface',
'[box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05)]',
'dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset]',
className
)}
>
<div>{background}</div>
<div className="p-4">
<div className="transform-gpu transition-all duration-300 lg:group-hover:-translate-y-10">
<SvgFinder
icon={icon}
size={38}
className="transform-gpu transition-all duration-300 group-hover:scale-75"
/>
<h3 className="text-xl font-semibold">{name}</h3>
<p className="text-neutral-foreground">{description}</p>
</div>
<div className="transform-gpu transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100 lg:hidden">
<Button variant="link" asChild>
<a href={href}>{cta}</a>
</Button>
</div>
</div>
</div>
);Props
BentoGrid
interface IBentoGridProps {
children: ReactNode;
className?: string;
}BentoCard
interface IBentoCardProps {
name: string; // Card title
className: string; // Grid positioning classes
background: ReactNode; // Background element (image, video, gradient)
icon: string; // Icon name for SvgFinder
description: string; // Card description
href: string; // Link destination
cta: string; // Call-to-action text
}Responsive Behavior
- Mobile: Single column, CTA always visible
- Desktop: Multi-column grid, CTA appears on hover
- Smooth transitions between breakpoints
Best Practices
- Use descriptive card names
- Keep descriptions concise (2-3 lines)
- Choose appropriate grid spans for content
- Use consistent background styles
- Ensure sufficient contrast for readability
- Test hover interactions on desktop
How is this guide ?
Last updated on