Bento Grid
Responsive bento layout of linked feature tiles.
pnpm dlx @glinui/cli@latest add bento-gridRealtime sync
Edits appear for everyone in under 100ms.
Audit log
Every change, with who and when.
Plugins
Extend the workspace with your own blocks.
SSO
SAML and SCIM on every paid plan.
Installation
pnpm dlx @glinui/cli@latest add bento-gridCredits. Adapted from Magic UI (MIT, (c) Magic UI). Responsive columns, whole tile anchor with a keyboard reachable action, lift and glass surfaces, Phosphor arrow mirrored for RTL. Attribution details.
Prefer the package?
Usage
The original nested a link button inside a div and revealed it on hover only, which keyboard users could not reach. Here the CTA is a styled span inside the single anchor, shown on hover, focus-visible and always on coarse pointers.
Engines: this component drives its main animation through the pluggable motion engine. Pass `engine` (css, motion or gsap), wrap a subtree in `MotionEngineProvider`, or set `data-glin-engine` on `<html>`. The css engine is built in and dependency free; motion and gsap are opt-in via `@glinui/motion/register/*`. `motion="none"` renders the final state and `subtle` is opacity only.
Variants
glinr is the default, plain is flat shadcn, solid is a neutral tonal face, glass is opt-in and needs a backdrop.
glinr
Bento tile surface.
Linked
The whole tile is one anchor.
Openplain
Bento tile surface.
Linked
The whole tile is one anchor.
Opensolid
Bento tile surface.
Linked
The whole tile is one anchor.
Openglass
Bento tile surface.
Linked
The whole tile is one anchor.
Openimport { BentoCard, BentoGrid } from "@glinui/ui"
// Omit `variant` to follow the ambient style (glinr by default).export function BentoGridVariants() { return ( <> <BentoCard variant="glinr" name="..." description="..." /> ... <BentoCard variant="plain" name="..." description="..." /> ... <BentoCard variant="solid" name="..." description="..." /> ... <BentoCard variant="glass" name="..." description="..." /> ... </> )}Colors
Tile washes follow the tone tokens.
accent
Tile wash follows the tone token.
success
Tile wash follows the tone token.
warning
Tile wash follows the tone token.
danger
Tile wash follows the tone token.
info
Tile wash follows the tone token.
import { BentoCard, BentoGrid } from "@glinui/ui"
export function BentoGridTones() { return ( <BentoCard name="Success" description="..." background={<Wash tone="success" />} /> ... )}In a layout
A landing section built from bento tiles.
Everything in one place
A landing section built from bento tiles.
// A landing section built from bento tiles.import { BentoCard, BentoGrid } from "@glinui/ui"
export function BentoGridLayout() { return ( <section className="grid gap-4 sm:grid-cols-3"> ... </section> )}Engine comparison
The same component on the css, motion and gsap engines. Replay restarts all three.
CSS
Sync
Realtime edits.
Audit
Every change.
Motion
Sync
Realtime edits.
Audit
Every change.
GSAP
Sync
Realtime edits.
Audit
Every change.
// Same component, three engines. motion and gsap are opt-in:// import "@glinui/motion/register/motion"// import "@glinui/motion/register/gsap"<BentoGrid engine="css" entrance immediate> <BentoCard name="Sync" description="Realtime edits." /> <BentoCard name="Audit" description="Every change." /></BentoGrid>
<BentoGrid engine="motion" entrance immediate> <BentoCard name="Sync" description="Realtime edits." /> <BentoCard name="Audit" description="Every change." /></BentoGrid>
<BentoGrid engine="gsap" entrance immediate> <BentoCard name="Sync" description="Realtime edits." /> <BentoCard name="Audit" description="Every change." /></BentoGrid>Accessibility
- Cards with href are single anchors, so one tab stop per card, with a visible focus ring.
- Decorative backgrounds and icons are aria-hidden.
- CTA is available without hover: focus reveals it on fine pointers, touch always shows it.
Keyboard Interactions
| Key | Action |
|---|---|
| Tab | Moves between linked cards. |
| Enter | Follows the focused card link. |
ARIA Attributes
- Card name is a real heading
- Icon and background are `aria-hidden`
Reduced Motion
The hover lift, icon scale and CTA slide are removed with prefers-reduced-motion or motion level none. At level none the CTA is always visible.
Affected properties
translate lifticon scaleCTA slide and fadeAPI Reference
BentoGrid
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
className | string | - | - | Use col-span and row-span classes on cards. Default columns: 1, sm 2, lg 3. |
background | React.ReactNode | No | - | Decorative background layer (pattern, gradient, illustration). Hidden from assistive tech. |
cta | string | No | - | Call to action label, shown with an arrow when `href` is set. |
description | string | Yes | - | Auto-generated from TypeScript source. |
headingLevel | 2 | 3 | 4 | No | 3 | Heading level for the card name. |
href | string | No | - | When set the whole card is a single anchor. |
Icon | React.ElementType<{ className?: string; "aria-hidden"?: boolean }> | No | - | Icon component (Phosphor icons work). Rendered decoratively. |
name | string | Yes | - | Card title, rendered as a heading. |
rel | string | No | - | Auto-generated from TypeScript source. |
target | React.HTMLAttributeAnchorTarget | No | - | Auto-generated from TypeScript source. |
variant | SurfaceVariant | "default" | null | No | - | Surface look. Omitted follows the ambient style (glinr by default). `glass` is opt-in and needs a backdrop. |
BentoCard
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | - | Title, rendered as a heading. |
description | string | Yes | - | Supporting copy. |
Icon | React.ElementType<{ className?: string; "aria-hidden"?: boolean }> | No | - | Decorative icon component (Phosphor). |
href | string | No | - | Makes the whole card an anchor. |
cta | string | No | - | CTA label shown with an arrow when href is set. |
background | React.ReactNode | No | - | Decorative layer behind the content, aria-hidden. |
variant | SurfaceVariant | "default" | null | No | ambient (glinr) | Tile surface. Glass is opt-in. |
headingLevel | 2 | 3 | 4 | No | 3 | Heading level for the name. |
rel | string | No | - | Auto-generated from TypeScript source. |
target | React.HTMLAttributeAnchorTarget | No | - | Auto-generated from TypeScript source. |
Source
Import directly from the package or browse the source on GitHub. Click any file to view it.
Import
import { BentoGrid } from "@glinui/ui"Dependencies
@glinui/ui@glinui/motionclass-variance-authority@phosphor-icons/reactGenerated API Snapshot
Beta
Generated API Snapshot
BetaAuto-extracted from TypeScript source in packages/ui/src/components/bento-grid.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.
Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata
Primary Props Type
BentoGridProps
BentoCardProps
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
background | React.ReactNode | No | - | Decorative background layer (pattern, gradient, illustration). Hidden from assistive tech. |
cta | string | No | - | Call to action label, shown with an arrow when `href` is set. |
description | string | Yes | - | - |
headingLevel | 2 | 3 | 4 | No | 3 | Heading level for the card name. |
href | string | No | - | When set the whole card is a single anchor. |
Icon | React.ElementType<{ className?: string; "aria-hidden"?: boolean }> | No | - | Icon component (Phosphor icons work). Rendered decoratively. |
name | string | Yes | - | Card title, rendered as a heading. |
rel | string | No | - | - |
target | React.HTMLAttributeAnchorTarget | No | - | - |
variant | SurfaceVariant | "default" | null | No | - | Surface look. Omitted follows the ambient style (glinr by default). `glass` is opt-in and needs a backdrop. |
BentoGridProps
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
duration | number | No | - | Per-card duration in ms. |
engine | EngineName | No | - | Engine override: `css` (default), `motion`, `gsap` or a registered custom engine. |
entrance | boolean | No | false | Reveal the cards in sequence when the grid enters the viewport. Off by default. |
immediate | boolean | No | false | Play on mount instead of waiting for the viewport. |
motion | MotionLevel | No | - | Motion override. `none` renders the static final state, `subtle` is opacity only. |
order | StaggerDirection | No | "forward" | Order the cards appear in. Default `forward`. |
step | number | No | 70 | Delay between cards in ms. Default 70. |
threshold | number | No | - | Visible fraction required to trigger. Default 0.15. |