caliper uidocs

Scene story block

Block

A chapter section told by scrolling, with a 3D scene beside it. As you read, the scene tips toward you and its layers spread apart, and the layer the chapter is about lights while the others dim. The chapters are complete without the scene.

Installs components/ui/scene-story-block.tsxDepends on @radix-ui/react-slot, lucide-reactMotion none in component source
pnpm dlx shadcn@latest add @caliper/scene-story-block

How it fits together

Three layers, one release

Scroll the chapters. The layer being described lights up.

Chapter 1

Your data, laid flat

Everything starts on the lowest plane: tables, events, the records that already exist. Nothing here is decorative.

Chapter 2

Logic on top of it

Rules and jobs sit one level up. You can see what each depends on, because it is directly above it.

Chapter 3

An interface for people

The top plane is what people touch. It is the only layer most of them ever see.

Chapter 4

All of it, shipping

The layers pull apart so each can change on its own. One release, three places to look.

When to use #

Use it for

  • Explaining a product or an architecture in layers: data, logic, interface.
  • Three to five chapters where each one names a part of a whole.

Skip it when

  • Content that is not about parts of one thing; use the steps block.
  • A hero. The scene explains; it does not decorate.

Decisions #

Why it is built this way, so you know what to keep when you change your copy.

Behaviour

The text stands on its own
The chapters are headed sections in a scrollable region. The scene is hidden from assistive technology and every fact in it is in the text.
Native scroll only
No scroll hijacking and nothing pinned. Tab and the arrow keys scroll the region, and a button per chapter jumps to it.

Usage

On phones the scene comes first
Under 600px the scene is shorter and sits above the text, which scrolls in its own box; each chapter keeps its lit layer.

Installation #

terminal
pnpm dlx shadcn@latest add @caliper/scene-story-block

Adds its 9 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

This is the code behind the preview above.

example.tsx
import { SceneStoryBlock, type SceneChapter } from "@/components/ui/scene-story-block"

const chapters: SceneChapter[] = [
  { eyebrow: "Chapter 1", title: "Your data, laid flat", text: "Everything starts on the lowest plane: tables, events, the records that already exist. Nothing here is decorative.", layer: 0 },
  { eyebrow: "Chapter 2", title: "Logic on top of it", text: "Rules and jobs sit one level up. You can see what each depends on, because it is directly above it.", layer: 1 },
  { eyebrow: "Chapter 3", title: "An interface for people", text: "The top plane is what people touch. It is the only layer most of them ever see.", layer: 2 },
  { eyebrow: "Chapter 4", title: "All of it, shipping", text: "The layers pull apart so each can change on its own. One release, three places to look.", layer: "all" },
];

export function SceneStoryBlockDemo() {
  return (
    <SceneStoryBlock
      eyebrow="How it fits together"
      title="Three layers, one release"
      lead="Scroll the chapters. The layer being described lights up."
      chapters={chapters}
      layers={["Data", "Logic", "Interface"]}
    />
  );
}

API reference #

SceneStoryBlock

component
PropTypeDefaultDescription
eyebrowstring—
title *string—
leadstring—
chapters *readonly SceneChapter[]—
layers *readonly string[]—Names of the scene's layers, bottom first. Three read best.
statusDepthStatus"ready"
messagesDepthMessages—
onRetry(() => void)—
disabledboolean—
classNamestring—

Accessibility #

It exposes region and group semantics, with aria-label, aria-labelledby, aria-hidden and aria-current kept in step with state.

No custom key handling; Tab and the native activation keys do the work.

Motion #

It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.