Elements

Components / Website

Bento

A standalone bento grid in the style of mode.com's “Beyond BI” section. Feature cards span a 12-column base grid with rounded corners and a seam-coloured gap between them.

Installation

bash
npx shadcn add https://raw.githubusercontent.com/levi-putna/elements/main/registry/bento/registry.json

How it works

  • The grid is a 12-column track. Each card sets a colSpan (and optional rowSpan), so spans of 7 + 5, or 4 + 3 + 5, fill a row. Auto-flow places them left-to-right, top-to-bottom.
  • The seamis the container background. It shows through every gap and the equal outer padding, so the frame and the inner gaps are one continuous colour; that's what the eye reads as the join between cards.
  • Cards stay rounded. Every cell keeps its corner radius on all four corners. The seam shows through the gaps between them.

Feature grid

Six capabilities on a 12-column grid, with one tall accent card.

default seam · feature cards

Ad hoc analysis

SQL, R and Python in one notebook.

Advanced analytics

Interactive modelling without the rebuild.

Self-serve reporting

Custom data apps

Interactive dashboards

Explorable datasets

tsx
import {
  BentoGrid,
  BentoFeatureCell,
} from "@/components/ui/bento"
import { Code2, LineChart, BarChart3, Boxes, LayoutDashboard, Database } from "lucide-react"

// 12-column base grid. Cells span a slice of it.
<BentoGrid seam="default" cols={12} rowHeight={168} gap={12}>
  <BentoFeatureCell icon={<Code2 />}        label="Ad hoc analysis"      tone="secondary" colSpan={7} />
  <BentoFeatureCell icon={<LineChart />}    label="Advanced analytics"   tone="primary"   colSpan={5} rowSpan={2} />
  <BentoFeatureCell icon={<BarChart3 />}    label="Self-serve reporting" tone="secondary" colSpan={4} />
  <BentoFeatureCell icon={<Boxes />}        label="Custom data apps"     tone="secondary" colSpan={3} />
  <BentoFeatureCell icon={<LayoutDashboard />} label="Interactive dashboards" tone="secondary" colSpan={7} />
  <BentoFeatureCell icon={<Database />}     label="Explorable datasets"  tone="secondary" colSpan={5} />
</BentoGrid>

Content grid

The editorial variant: BentoContentCell for eyebrow + display heading + copy, alongside BentoVisualCell fills for screenshots and UI previews.

secondary seam · content + visual

Built for managers

Made for your strata team

Levy notices, maintenance requests, AGM minutes and owner queries: all in one workspace.

SP12345

Owner experience

And the owners you serve

A self-service portal means fewer calls, more transparency, and owners who trust you.

tsx
import {
  BentoGrid,
  BentoContentCell,
  BentoVisualCell,
} from "@/components/ui/bento"

<BentoGrid seam="secondary" cols={2} rowHeight={220} gap={12}>
  <BentoContentCell
    eyebrow="Built for managers"
    heading="Made for your strata team"
    body="Levy notices, maintenance requests and owner queries in one workspace."
    tone="default"
  />
  <BentoVisualCell tone="primary">{/* screenshot */}</BentoVisualCell>
</BentoGrid>

BentoGrid Props

PropTypeDefaultDescription
seam"default" | "secondary" | "primary" | "alternative""default"Background of the container. Shows through every gap and the outer padding, so it reads as the seam between cards.
colsnumber12Base columns. Cells span a slice of these via colSpan.
rowHeightnumber168Height (px) of one grid row. Cells with rowSpan get multiples of this.
gapnumber12Gap between cells (px). Reused as the outer padding so the frame is even on every side.
roundednumber28Outer container radius (px). Keep it larger than the cell radius so the frame never clips a card corner.

BentoCell Props

PropTypeDefaultDescription
tone"default" | "secondary" | "primary" | "alternative" | "dark""secondary"Card background and text colour.
colSpannumber1Columns this cell spans, of the grid's cols.
rowSpannumber1Rows this cell spans.
radiusnumber18Corner radius of the card (px).
clipbooleanfalseClip overflowing content (images).

BentoFeatureCell Props

Extends BentoCell props.

PropTypeDefaultDescription
iconReactNode-24px icon (Lucide or any SVG) rendered at the top-left.
labelstring-Primary label pinned to the bottom-left.
bodystring-Optional supporting text under the label.
visualReactNode-Optional chart / screenshot placed between icon and label.