Glin UI
Primitive / OrganismAdapted from Magic UIbeta

Bento Grid

Responsive bento layout of linked feature tiles.

Edit on GitHub

Realtime 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

Install from
pnpm dlx @glinui/cli@latest add bento-grid

Credits. 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.

import { 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.

// 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

KeyAction
TabMoves between linked cards.
EnterFollows 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 fade

API Reference

BentoGrid

PropTypeRequiredDefaultDescription
classNamestring--Use col-span and row-span classes on cards. Default columns: 1, sm 2, lg 3.
backgroundReact.ReactNodeNo-Decorative background layer (pattern, gradient, illustration). Hidden from assistive tech.
ctastringNo-Call to action label, shown with an arrow when `href` is set.
descriptionstringYes-Auto-generated from TypeScript source.
headingLevel2 | 3 | 4No3Heading level for the card name.
hrefstringNo-When set the whole card is a single anchor.
IconReact.ElementType<{ className?: string; "aria-hidden"?: boolean }>No-Icon component (Phosphor icons work). Rendered decoratively.
namestringYes-Card title, rendered as a heading.
relstringNo-Auto-generated from TypeScript source.
targetReact.HTMLAttributeAnchorTargetNo-Auto-generated from TypeScript source.
variantSurfaceVariant | "default" | nullNo-Surface look. Omitted follows the ambient style (glinr by default). `glass` is opt-in and needs a backdrop.

BentoCard

PropTypeRequiredDefaultDescription
namestringYes-Title, rendered as a heading.
descriptionstringYes-Supporting copy.
IconReact.ElementType<{ className?: string; "aria-hidden"?: boolean }>No-Decorative icon component (Phosphor).
hrefstringNo-Makes the whole card an anchor.
ctastringNo-CTA label shown with an arrow when href is set.
backgroundReact.ReactNodeNo-Decorative layer behind the content, aria-hidden.
variantSurfaceVariant | "default" | nullNoambient (glinr)Tile surface. Glass is opt-in.
headingLevel2 | 3 | 4No3Heading level for the name.
relstringNo-Auto-generated from TypeScript source.
targetReact.HTMLAttributeAnchorTargetNo-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/react

Generated API Snapshot

Beta

Auto-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

PropTypeRequiredDefaultDescription
backgroundReact.ReactNodeNo-Decorative background layer (pattern, gradient, illustration). Hidden from assistive tech.
ctastringNo-Call to action label, shown with an arrow when `href` is set.
descriptionstringYes--
headingLevel2 | 3 | 4No3Heading level for the card name.
hrefstringNo-When set the whole card is a single anchor.
IconReact.ElementType<{ className?: string; "aria-hidden"?: boolean }>No-Icon component (Phosphor icons work). Rendered decoratively.
namestringYes-Card title, rendered as a heading.
relstringNo--
targetReact.HTMLAttributeAnchorTargetNo--
variantSurfaceVariant | "default" | nullNo-Surface look. Omitted follows the ambient style (glinr by default). `glass` is opt-in and needs a backdrop.

BentoGridProps

PropTypeRequiredDefaultDescription
durationnumberNo-Per-card duration in ms.
engineEngineNameNo-Engine override: `css` (default), `motion`, `gsap` or a registered custom engine.
entrancebooleanNofalseReveal the cards in sequence when the grid enters the viewport. Off by default.
immediatebooleanNofalsePlay on mount instead of waiting for the viewport.
motionMotionLevelNo-Motion override. `none` renders the static final state, `subtle` is opacity only.
orderStaggerDirectionNo"forward"Order the cards appear in. Default `forward`.
stepnumberNo70Delay between cards in ms. Default 70.
thresholdnumberNo-Visible fraction required to trigger. Default 0.15.