Card

Bento Window

Glass-window row that slices one painting across several framed windows, with helpers for offsets and mullion seams, caption parts and an optional 60s pan that stops under reduced motion.

The source comes with full access.

One payment of $149 ($49 for now) opens the source right here and lets the CLI install every paid component, with lifetime updates.

Installation

pnpm dlx shadcn add @01orbital/bento-window
npx shadcn add @01orbital/bento-window
yarn shadcn add @01orbital/bento-window
bunx --bun shadcn add @01orbital/bento-window

Part of the 01orbital library. With a license, put ORBITAL_TOKEN in .env.local and the same command installs it (licensed install, pricing).

It lands at components/card/bento-window.tsx, as source you own and edit.

The example also uses orbital-limb-scene. Install it too:

pnpm dlx shadcn add @01orbital/orbital-limb-scene
npx shadcn add @01orbital/orbital-limb-scene
yarn shadcn add @01orbital/orbital-limb-scene
bunx --bun shadcn add @01orbital/orbital-limb-scene

Usage

import {
  GlassWindow,
  GlassWindowArt,
  GlassWindowRow,
  WindowCaption,
  WindowEyebrow,
  WindowTitle,
} from "@/components/card/bento-window"
import { OrbitalLimbScene } from "@/components/scene/orbital-limb-scene"

// Every word on the page. Change copy here, not in the markup.
const COPY = {
  eyebrow: "Capture",
  title: "Every channel, one queue",
  eyebrow2: "Inbox agent",
  title2: "Night shift covered",
} as const

const orb = { limbX: 50, x: 12, size: 116 } as const

// Two windows on one row: the same sky continues behind the wall between them.
export default function BentoWindowDemo() {
  return (
    <GlassWindowRow tracks={[1, 1]} className="w-full max-w-4xl">
      <GlassWindow className="h-85">
        <GlassWindowArt offset={0} width={896}>
          <OrbitalLimbScene horizon={58} orb={orb} light={{ key: "dual" }} />
        </GlassWindowArt>
        <WindowCaption>
          <WindowEyebrow>{COPY.eyebrow}</WindowEyebrow>
          <WindowTitle>{COPY.title}</WindowTitle>
        </WindowCaption>
      </GlassWindow>
      <GlassWindow className="h-85">
        <GlassWindowArt offset={450} width={896}>
          <OrbitalLimbScene horizon={58} orb={orb} light={{ key: "dual" }} />
        </GlassWindowArt>
        <WindowCaption>
          <WindowEyebrow>{COPY.eyebrow2}</WindowEyebrow>
          <WindowTitle>{COPY.title2}</WindowTitle>
        </WindowCaption>
      </GlassWindow>
    </GlassWindowRow>
  )
}

Anatomy

Bento Window is built from 7 parts. In the example they nest like this:

GlassWindowRow
└─ GlassWindow
   ├─ GlassWindowArt
   └─ WindowCaption
      ├─ WindowEyebrow
      └─ WindowTitle
  • GlassWindowRow: The row that holds the GlassWindows. The windows stack in one column on small screens and sit side by side from the md breakpoint, 2px apart.
  • GlassWindow: One window onto the shared painting. It clips a GlassWindowArt and a WindowCaption to its rounded corners and draws a faint inset ring on top of them as its frame. Text inside uses the scene foreground color.
  • GlassWindowArt: The painting behind one GlassWindow. It renders the full scene at width and shifts it left by offset, so a row of windows reads as slices of one picture. Put the same art in every window.
  • WindowCaption: The text over a GlassWindow, placed 32px in from the sides and from the top or bottom edge. Put a WindowEyebrow, WindowTitle and WindowBody inside.
  • WindowEyebrow: A small semibold label above a WindowTitle, with a soft text shadow so it stays readable over the art.
  • WindowTitle: The heading of a WindowCaption, an h3 in the display font. Pass render to use another heading level.
  • WindowBody: Supporting text under a WindowTitle. It uses the text color at 85% rather than a muted tone, so it stays readable over a bright horizon in the art.

API reference

GlassWindowRow

The row that holds the GlassWindows. The windows stack in one column on small screens and sit side by side from the md breakpoint, 2px apart.

The row is a container, so a painting sized by bentoWindows spans the whole row. Its 2px gap matches the default gap of bentoWindows.

Prop

Type

It also accepts the HTML attributes of the element it renders.

GlassWindow

One window onto the shared painting. It clips a GlassWindowArt and a WindowCaption to its rounded corners and draws a faint inset ring on top of them as its frame. Text inside uses the scene foreground color.

Its contents are placed absolutely and give it no height, so set one with className.

It accepts the HTML attributes of the element it renders.

GlassWindowArt

The painting behind one GlassWindow. It renders the full scene at width and shifts it left by offset, so a row of windows reads as slices of one picture. Put the same art in every window.

The shift applies from the md breakpoint, where the windows sit side by side; below it, each window shows the painting's left edge.

Prop

Type

It also accepts the HTML attributes of the element it renders.

WindowCaption

The text over a GlassWindow, placed 32px in from the sides and from the top or bottom edge. Put a WindowEyebrow, WindowTitle and WindowBody inside.

Prop

Type

It also accepts the HTML attributes of the element it renders.

WindowEyebrow

A small semibold label above a WindowTitle, with a soft text shadow so it stays readable over the art.

It accepts the HTML attributes of the element it renders.

WindowTitle

The heading of a WindowCaption, an h3 in the display font. Pass render to use another heading level.

It accepts the props of the Base UI part it wraps, and the HTML attributes of the element it renders.

WindowBody

Supporting text under a WindowTitle. It uses the text color at 85% rather than a muted tone, so it stays readable over a bright horizon in the art.

It accepts the HTML attributes of the element it renders.

Dependencies

npm: @base-ui/react, cn. The CLI installs them for you.

Registry pieces it installs with it:

  • font-hanken-grotesk