Bento Grid
Preview: Default
Bento layout: a 3-column grid (one column on small screens) of feature cards with varied spans, placed in DOM order.
Import
import { BentoGrid, BentoCard } from '@marbleui/ui'Props
<BentoGrid>
| Prop | Type | Default | Description |
|---|---|---|---|
| children *required | ReactNode | — | |
| className | string | — |
<BentoCard>
Feature card for BentoGrid: background art, icon, title, description, and a CTA that slides up on hover/focus. With `href` the card is a link; without one it's a static card with no CTA (no dead `#` links).
| Prop | Type | Default | Description |
|---|---|---|---|
| description *required | string | — | |
| title *required | string | — | |
| background | ReactNode | — | |
| className | string | — | |
| cta | string | 'Learn more' | |
| href | string | — | |
| icon | ReactNode | — | |
| rows | 1 | 2 | 1 | |
| span | 1 | 2 | 3 | 1 |
Usage notes
Marketing grid of linked feature cards in mixed sizes: three columns from the sm breakpoint, one below, rows 14 rem tall. For app layouts use Grid.
<BentoGrid>
<BentoCard span={2} title="Search everything" description="Issues, docs and people in one palette." icon={<SearchIcon />} href="/features/search" />
<BentoCard rows={2} title="Agents" description="Hand off tasks; approve risky steps." href="/features/agents" cta="See agents" />
<BentoCard title="Themes" description="Two presets, dark mode." href="/features/themes" />
</BentoGrid>
- Each
BentoCardis one link whose accessible name is all its text, including thecta(default “Learn more”). Withouthrefthe card is static: not a link, and no CTA. span(1–3 columns) androws(1 or 2) apply fromsmup. The grid doesn’t backfill gaps, so make each row add up to three.- Rows are a fixed height and cards clip overflow, so keep text short.
backgroundart is hidden from assistive tech. - The CTA slides in on hover and keyboard focus; under
prefers-reduced-motionit fades in without sliding, and the background doesn’t zoom.
Example source · show· hide
import { BentoCard, BentoGrid } from './bento-grid'
const I = ({ d }: { d: string }) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d={d} /></svg>
const Bg = ({ h }: { h: number }) => <div className="size-full" style={{ background: `radial-gradient(circle at 80% 20%, color-mix(in oklab, var(--chart-${h}) 45%, transparent), transparent 60%)` }} />
export const styles = {
Default: () => (
<BentoGrid className="w-[44rem] max-w-full">
<BentoCard span={2} title="Search everything" description="Issues, docs and people from one command palette." icon={<I d="M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16M21 21l-4.3-4.3" />} background={<Bg h={1} />} />
<BentoCard rows={2} title="Agents" description="Hand off tasks; approve the risky steps." icon={<I d="M12 3v4M12 17v4M3 12h4M17 12h4" />} background={<Bg h={6} />} />
<BentoCard title="Charts" description="Validated palettes." icon={<I d="M3 3v18h18M7 16l4-4 4 4 5-6" />} background={<Bg h={4} />} />
<BentoCard title="Themes" description="Two presets, dark mode." icon={<I d="M12 22a10 10 0 1 1 10-10c0 2.5-2 4-4.5 4H15a2 2 0 0 0-1.5 3.3A2 2 0 0 1 12 22" />} background={<Bg h={5} />} />
</BentoGrid>
),
}Source: packages/ui/src/bento-grid/bento-grid.tsx
Catalog
- Category
- layout
- Priority
- Extra
- Primitive
- custom