# Bento Grid

A three-column asymmetric feature grid with BentoGrid and BentoCard, including background, icon, description, and call-to-action slots that reveal on hover.

- Category: Data Display
- License: MIT
- Page: https://www.saasuji.com/components/bento-grid
- Install: npx shadcn@latest add https://www.saasuji.com/r/bento-grid.json

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| children (BentoGrid) | `React.ReactNode` | — | BentoCard children laid out in a three-column auto-rows grid. |
| className (BentoGrid) | `string` | — | Additional classes merged onto the grid; controls column counts and gaps. |
| name (BentoCard) | `string` | — | Card heading; required. |
| className (BentoCard) | `string` | — | Additional classes merged onto the card; required, and typically sets col-span and row-span. |
| background (BentoCard) | `React.ReactNode` | — | Decorative node rendered behind the content, typically an absolutely positioned gradient. |
| Icon (BentoCard) | `React.ElementType` | — | Icon component rendered above the card name. |
| description (BentoCard) | `string` | — | Supporting copy rendered under the card name. |
| href (BentoCard) | `string` | — | Link target for the call-to-action button. |
| cta (BentoCard) | `string` | — | Call-to-action label next to the arrow icon. |
| ...props (BentoGrid, BentoCard) | `React.ComponentPropsWithoutRef<"div">` | — | All remaining native div attributes are forwarded. |

## Source

```tsx
import { type ComponentPropsWithoutRef, type ReactNode } from "react"
import { ArrowRightIcon } from "@radix-ui/react-icons"

import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"

interface BentoGridProps extends ComponentPropsWithoutRef<"div"> {
  children: ReactNode
  className?: string
}

interface BentoCardProps extends ComponentPropsWithoutRef<"div"> {
  name: string
  className: string
  background: ReactNode
  Icon: React.ElementType
  description: string
  href: string
  cta: string
}

const BentoGrid = ({ children, className, ...props }: BentoGridProps) => {
  return (
    <div
      className={cn(
        "grid w-full auto-rows-[22rem] grid-cols-3 gap-4",
        className
      )}
      {...props}
    >
      {children}
    </div>
  )
}

const BentoCard = ({
  name,
  className,
  background,
  Icon,
  description,
  href,
  cta,
  ...props
}: BentoCardProps) => (
  <div
    key={name}
    className={cn(
      "group relative col-span-3 flex flex-col justify-between overflow-hidden rounded-xl",
      // light styles
      "bg-background [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]",
      // dark styles
      "dark:bg-background transform-gpu dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset] dark:[border:1px_solid_rgba(255,255,255,.1)]",
      className
    )}
    {...props}
  >
    <div>{background}</div>
    <div className="p-4">
      <div className="pointer-events-none z-10 flex flex-col gap-1">
        <Icon className="h-12 w-12 text-neutral-700" />
        <h3 className="text-xl font-semibold text-neutral-700 dark:text-neutral-300">
          {name}
        </h3>
        <p className="max-w-lg text-neutral-400">{description}</p>
      </div>

      <div
        className={cn(
          "pointer-events-none flex w-full translate-y-0 transform-gpu flex-row items-center transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100 lg:hidden"
        )}
      >
        <Button
          variant="link"
          asChild
          size="sm"
          className="pointer-events-auto p-0"
        >
          <a href={href}>
            {cta}
            <ArrowRightIcon className="ms-2 h-4 w-4 rtl:rotate-180" />
          </a>
        </Button>
      </div>
    </div>

    <div
      className={cn(
        "pointer-events-none absolute bottom-0 hidden w-full translate-y-10 transform-gpu flex-row items-center p-4 opacity-0 transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100 lg:flex"
      )}
    >
      <Button
        variant="link"
        asChild
        size="sm"
        className="pointer-events-auto p-0"
      >
        <a href={href}>
          {cta}
          <ArrowRightIcon className="ms-2 h-4 w-4 rtl:rotate-180" />
        </a>
      </Button>
    </div>

    <div className="pointer-events-none absolute inset-0 transform-gpu transition-all duration-300 group-hover:bg-black/3 group-hover:dark:bg-neutral-800/10" />
  </div>
)

export { BentoCard, BentoGrid }

```
