Skip to content
txbrendan/ui

Scene

beta

A picture drawn from the theme with something light floating on it: tiles, a preview card, people, or a hint.

Preview

SceneTiles on lake

ScenePreview on frost

ScenePeople on golden

SceneHint on dusk, at sm

frost
alpine
golden
lake
coast
clubhouse
dusk
floodlights

Install

  1. 1. Add the registry to components.json, once per app. Without it, the shadcn CLI looks up @txbrendan in a public list that txbrendan/ui does not control.

    npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"
  2. 2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.

    npx shadcn@latest add @txbrendan/theme
  3. 3. Add the component.

    npx shadcn@latest add @txbrendan/scene

Use it for

  • The top of an empty state that's a first step, a call to action, or a popup in a card. Inset it 6px from the card's edge, like p-1.5.
  • It shows what's missing or what's next. What people must read goes under it, in the card.
  • Float one thing on it. SceneTiles: up to three tiles, for what a feature brings together. ScenePreview: the real thing a feature makes, like "Q4 launch plan", with cursors for work done together. ScenePeople: up to four faces joined by a link, for sharing or a team. SceneHint: one round icon with a dark hint, for the one thing a step asks.
  • Pick a backdrop: frost (the default, pale and quiet), alpine, golden, the blue lake, coast, and clubhouse, or the dark dusk and floodlights. Or pass image for a picture of your own.
  • Use size sm (120px) in a popup.

Avoid it for

  • More than one scene on a surface.
  • A row, a list, or a chart. A scene is for the top of a card.
  • Words people must read. Put them under the scene: a label only names it for screen readers.

Props

  • backdrop

    A picture drawn from the theme's colors. dusk and floodlights stay dark in both themes.

    "frost" | "alpine" | "lake" | "coast" | "clubhouse" | "dusk" | "golden" | "floodlights" · default "frost"

  • image

    A picture of your own instead, as a URL.

    string

  • position

    Where the picture is anchored, as a background-position: "center 70%".

    string

  • size

    Scene, SceneTiles, and ScenePeople. A scene is 120px at sm, for a popup, 160px at md, and 200px at lg. Tiles are 48, 64, or 80px. Faces are 28, 36, or 44px.

    "sm" | "md" | "lg" · default "md"

  • label

    Says what it shows to screen readers. Without it the scene is hidden from them.

    string

  • className

    Extra classes on the scene. Later classes win.

    string

  • SceneTiles

    Part. Up to three tiles rising left to right. SceneTile is { spot?: ReactNode; icon?: ReactNode; src?: string; tag?: string }.

    { tiles: SceneTile[]; size?: "sm" | "md" | "lg" }

  • ScenePreview

    Part. A card rising from the bottom, with a second card behind it. value is the change, in the brand color. lines defaults to 2. Two cursors at most: yours first, in tone "neutral".

    { title: string; spot?: ReactNode; src?: string; value?: string; lines?: number; cursors?: { name: string; tone?: "neutral" | "brand" }[] }

  • ScenePeople

    Part. Up to four faces on an arch, with icon in the middle. Default a link.

    { people: { name: string; src?: string }[]; icon?: ReactNode; size?: "sm" | "md" | "lg" }

  • SceneHint

    Part. One round icon with a dark hint under it: "Pair tablet".

    { icon: ReactNode; label?: string }

Accessibility

  • Without label, the whole scene is hidden from screen readers, since the words under it say what it shows.
  • With label, it is one image with that name, and what floats on it is part of the picture.
  • The floating parts are cards with a border, so forced-colors mode keeps their edges.
  • They pop in a beat apart. Reduced motion keeps only the fade.

Examples

At the top of a call to action

import { CalendarDays, Coins, Users } from "lucide-react";

<Card className="max-w-sm gap-0 p-1.5">
  <Scene backdrop="lake">
    <SceneTiles tiles={[{ spot: <CalendarDays /> }, { spot: <Users /> }, { spot: <Coins />, tag: "New" }]} />
  </Scene>
  <p className="p-3">Events, people and invoices, in one place.</p>
</Card>