# Bento Grid 1

> Solace UI bento grid block variation 1.

A shadcn/ui block from the [@solaceui](https://www.solaceui.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/solaceui/bento-grid-1).

- Page, with a live preview: https://shadcn.exchange/r/solaceui/bento-grid-1
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/solaceui/bento-grid-1-light-44d1a8f3a8233400.png
- Registry item: https://www.solaceui.com/r/bento-grid-1.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://www.solaceui.com/r/bento-grid-1.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `motion`

## Files

### `src/registry/blocks/bento-grid/one/index.tsx`

```tsx
import {
    BentoGrid,
    BentoItem,
    ChatMessaging,
    CompanyLogos,
} from "@/registry/blocks/bento-grid/one/bento-grid-template-one";

export default function BentoGridOne() {
    const items: BentoItem[] = [
        {
            id: "1",
            type: "feature",
            title: "World-Class Information Design",
            description:
                "Transform complex data into crisp visuals that quickly tell your story.",
            image:
                "https://assets.solaceui.com/solaceui-hero-video.jpg",
        },
        {
            id: "2",
            type: "chat",
            content: <ChatMessaging />,
        },
        {
            id: "3",
            type: "partners",
            title: "Connected Everywhere",
            description:
                "Embed your work seamlessly across your favorite platforms for instant sharing.",
            content: <CompanyLogos />,
        },
    ];

    return (
        <main className="flex min-h-screen flex-col items-center justify-center p-4 md:p-24 ">
            <BentoGrid items={items} />
        </main>
    );
}
```

### `src/registry/blocks/bento-grid/one/bento-grid-template-one.tsx`

```tsx
"use client";

import type { ReactNode } from "react";
import { motion } from "motion/react";
import Image from "next/image";
import { cn } from "@/lib/utils";

// Types for our bento grid items
export type BentoItem = {
    id: string;
    type: "feature" | "chat" | "partners";
    title?: string;
    description?: string;
    image?: string;
    className?: string;
    content?: ReactNode;
};

// Props for our base BentoGrid component
interface BentoGridProps {
    items: BentoItem[];
    className?: string;
}

// Props for each bento item
interface BentoItemProps {
    item: BentoItem;
    className?: string;
}

// Base BentoGrid component
export function BentoGrid({ items, className }: BentoGridProps) {
    return (
        <div
            className={cn(
                "grid grid-cols-1 md:grid-cols-2 gap-4 max-w-7xl mx-auto",
                className
            )}
        >
            {items.map((item) => {
                return (
                    <div
                        key={item.id}
                        className={cn(
                            "row-span-1",
                            item.type === "feature" && "col-span-1 md:col-span-2",
                            item.className
                        )}
                    >
                        <BentoGridItem item={item} />
                    </div>
                );
            })}
        </div>
    );
}

// Individual BentoGridItem component
function BentoGridItem({ item, className }: BentoItemProps) {
    const { type, title, description, image, content } = item;

    // Different layouts based on item type
    switch (type) {
        case "feature":
            return (
                <motion.div
                    initial={{ opacity: 0, y: 20 }}
                    animate={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5 }}
                    className={cn(
                        "group relative overflow-hidden rounded-xl bg-[#19ffc2ec] dark:bg-neutral-900 p-8 h-[400px] flex flex-col md:flex-row shadow-md",
                        className
                    )}
                >
                    <div className="flex flex-col justify-center z-10 md:w-1/2">
                        <span className="text-xs uppercase  dark:text-[#1DCD9F] text-black font-medium mb-2">
                            Visualise Info
                        </span>
                        <h2 className="text-3xl md:text-4xl font-bold  dark:text-white text-black mb-4 text-balance">
                            {title}
                        </h2>
                        <p className="text-sm text-neutral-600 max-w-md text-balance">
                            {description}
                        </p>
                    </div>

                    {image && (
                        <div className=" md:w-1/2 h-full right-0 top-0 flex items-center justify-center">
                            <div className="relative w-full h-full">
                                <motion.div
                                    initial={{ rotate: 0 }}
                                    animate={{ scale: 1.1 }}
                                    transition={{ duration: 0.7 }}
                                    className="absolute inset-0 z-0"
                                >
                                    <div className="relative w-full h-full top-10 left-10">
                                        <Image
                                            src={image || "/placeholder.svg"}
                                            alt="visualise"
                                            fill
                                            className="object-cover rounded-md shadow-xl dark:shadow-[#1DCD9F] shadow-white"
                                          unoptimized
                                        />
                                    </div>
                                </motion.div>
                            </div>
                        </div>
                    )}
                    <div className="absolute bottom-0 z-50 inset-x-0 h-[2rem] bg-gradient-to-t dark:from-neutral-900 from-[#1DCD9F] to-transparent w-full pointer-events-none" />
                </motion.div>
            );

        case "chat":
            return (
                <motion.div
                    initial={{ opacity: 0, y: 20 }}
                    animate={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.1 }}
                    className={cn(
                        "group relative overflow-hidden rounded-xl bg-[#222222] dark:bg-neutral-900 p-8 h-[400px] flex flex-col shadow-md",
                        className
                    )}
                >
                    <div className="z-10">
                        <span className="text-xs uppercase text-[#1DCD9F] font-medium mb-2 flex items-center justify-center p-2">
                            Customise
                        </span>
                    </div>

                    <div className="flex-1 relative">{content}</div>
                    <div className="absolute bottom-0 z-50 inset-x-0 h-[2rem] bg-gradient-to-t from-neutral-900 to-transparent w-full pointer-events-none" />
                </motion.div>
            );

        case "partners":
            return (
                <motion.div
                    initial={{ opacity: 0, y: 20 }}
                    animate={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.2 }}
                    className={cn(
                        "group relative overflow-hidden rounded-xl bg-neutral-900 p-8 h-[400px] flex flex-col shadow-md",
                        className
                    )}
                >
                    <div className="flex-1 relative flex items-center justify-center">
                        {content}
                        <div className="absolute left-0 z-[100] inset-y-0 w-10 bg-gradient-to-r from-neutral-900 to-transparent  h-full pointer-events-none" />
                        <div className="absolute right-0 z-[100] inset-y-0 w-10 bg-gradient-to-l from-neutral-900  to-transparent h-full pointer-events-none" />
                    </div>

                    <div className="mt-4 z-10">
                        <span className="text-xs uppercase text-[#1DCD9F] font-medium ">
                            Embed
                        </span>
                        <h3 className="text-2xl font-bold text-white mb-2 text-balance">
                            {title}
                        </h3>
                        <p className="text-sm dark:text-neutral-600 text-neutral-700 text-balance">
                            {description}
                        </p>
                    </div>
                </motion.div>
            );

        default:
            return null;
    }
}

// Company logos component for the partners section
export function CompanyLogos() {
    const logos = [
        {
            name: "Spotify",
            url: "https://assets.solaceui.com/solaceui-Spotify.png",
        },
        {
            name: "Notion",
            url: "https://assets.solaceui.com/solaceui-Notion.png",
        },
        {
            name: "Slack",
            url: "https://assets.solaceui.com/solaceui-Slack.png",
        },
        {
            name: "Twitter",
            url: "https://assets.solaceui.com/solaceui-Twitter.png",
        },
        {
            name: "Apple",
            url: "https://assets.solaceui.com/solaceui-Apple.png",
        },
    ];

    return (
        <div className="w-full overflow-hidden">
            <motion.div
                className="flex gap-8 items-center justify-center"
                animate={{ x: [0, -1000] }}
                transition={{
                    x: {
                        repeat: Number.POSITIVE_INFINITY,
                        repeatType: "loop",
                        duration: 20,
                        ease: "linear",
                    },
                }}
            >
                {/* First set of logos */}
                {logos.map((logo) => (
                    <div
                        key={logo.name}
                        className="flex-shrink-0 w-16 h-16 bg-neutral-800 rounded-lg flex items-center justify-center p-2"
                    >
                        <Image
                            src={logo.url || "/placeholder.svg"}
                            alt={logo.name}
                            width={40}
                            height={40}
                            className="w-10 h-10 object-contain"
                          unoptimized
                        />
                    </div>
                ))}

                {/* Duplicate set for seamless looping */}
                {logos.map((logo) => (
                    <div
                        key={`${logo.name}-dup`}
                        className="flex-shrink-0 w-16 h-16 bg-neutral-800 rounded-lg flex items-center justify-center p-2"
                    >
                        <Image
                            src={logo.url || "/placeholder.svg"}
                            alt={logo.name}
                            width={40}
                            height={40}
                            className="w-10 h-10 object-contain"
                          unoptimized
                        />
                    </div>
                ))}
            </motion.div>
        </div>
    );
}

// Chat messaging component with iPhone mockup
export function ChatMessaging() {
    return (
        <div className="relative w-full h-full flex items-center justify-center">
            <div className="relative w-[280px] h-[500px] bg-neutral-800 rounded-[36px] p-3 border-4 border-neutral-700 overflow-hidden">
                <div className="absolute top-0 left-1/2 transform -translate-x-1/2 w-1/3 h-6 bg-neutral-700 rounded-b-xl z-10" />
                <div className="w-full h-full bg-neutral-900 rounded-[28px] p-4 overflow-hidden">
                    <div className="flex items-center mb-4">
                        <div className="w-8 h-8 rounded-full bg-[#1DCD9F] mr-3" />
                        <div>
                            <div className="text-white text-xs font-medium">Assistant</div>
                            <div className="text-neutral-400 text-[10px]">Online</div>
                        </div>
                    </div>

                    <div className="space-y-3">
                        <motion.div
                            initial={{ opacity: 0, x: -20 }}
                            animate={{ opacity: 1, x: 0 }}
                            transition={{ duration: 0.5 }}
                            className="bg-neutral-800 p-2 rounded-lg rounded-tl-none max-w-[80%] text-[10px] text-white"
                        >
                            How can I help you today?
                        </motion.div>

                        <motion.div
                            initial={{ opacity: 0, x: 20 }}
                            animate={{ opacity: 1, x: 0 }}
                            transition={{ duration: 0.5, delay: 0.3 }}
                            className="bg-[#1DCD9F] p-2 rounded-lg rounded-tr-none max-w-[80%] ml-auto text-[10px] text-white"
                        >
                            I need help with my project
                        </motion.div>

                        <motion.div
                            initial={{ opacity: 0, x: -20 }}
                            animate={{ opacity: 1, x: 0 }}
                            transition={{ duration: 0.5, delay: 0.6 }}
                            className="bg-neutral-800 p-2 rounded-lg rounded-tl-none max-w-[80%] text-[10px] text-white"
                        >
                            I&apos;d be happy to help! What kind of project are you working
                            on?
                        </motion.div>

                        <motion.div
                            initial={{ opacity: 0, x: 20 }}
                            animate={{ opacity: 1, x: 0 }}
                            transition={{ duration: 0.5, delay: 0.9 }}
                            className="bg-[#1DCD9F] p-2 rounded-lg rounded-tr-none max-w-[80%] ml-auto text-[10px] text-white"
                        >
                            I&apos;m building a component library with Next.js and Tailwind
                        </motion.div>
                    </div>
                </div>
            </div>
        </div>
    );
}
```
