Layout Composition

Stage Manager Scenes

A stage-managed layout — the main scene sits center stage while the rest stack as tilted thumbnails in a sidebar, swapping places with shared-element FLIP and a depth-of-field blur when selected.

This is a WebberUI Pro component

The install command below needs a licence to run; without one it returns 401.

How to install Pro components →See the plans →

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add "https://webberui.com/r/stage-manager-scenes.en.json?t=<install token>"

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

Active edited usageDefault props
<StageManagerScenes/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add "https://webberui.com/r/stage-manager-scenes.en.json?t=<install token>"

Or, once registries are configured in components.json, install it as @webberui/stage-manager-scenes.

Usage

Declare each scene with StageManagerScene, and StageManagerScenes puts the currently selected one center stage while shrinking the rest into sidebar thumbnails. Clicking a thumbnail swaps positions with a shared-element FLIP animation.

import {
  StageManagerScene,
  StageManagerScenes,
} from "@/components/ui/stage-manager-scenes";

<div className="h-[300px] w-full max-w-md">
  <StageManagerScenes defaultActiveId="mail">
    <StageManagerScene id="mail" label="Inbox">
      <div className="flex h-full items-center justify-center bg-sky-600 text-white">
        Inbox
      </div>
    </StageManagerScene>
    <StageManagerScene id="calendar" label="Calendar">
      <div className="flex h-full items-center justify-center bg-rose-500 text-white">
        Calendar
      </div>
    </StageManagerScene>
  </StageManagerScenes>
</div>

Controlled mode: hold activeId yourself and update it in onActiveChange.

const [active, setActive] = React.useState("mail");

<StageManagerScenes activeId={active} onActiveChange={setActive}>
  {/* ...scenes */}
</StageManagerScenes>

Props

StageManagerScenes

PropTypeDefaultDescription
activeIdstring—Controlled: the id of the scene currently center stage
defaultActiveIdstringfirst sceneInitial stage scene id in uncontrolled mode
onActiveChange(id: string) => void—Fires when the stage scene changes (called in both controlled and uncontrolled modes)
side"left" | "right""left"Which side the thumbnail sidebar sits on
labelstring"Stage Scheduling"Accessible label for the whole stage-managed region
childrenReactNode—Several StageManagerScene children

StageManagerScene

PropTypeDefaultDescription
idstring—Unique scene identifier, used as the controlled value and the FLIP pairing key
labelstring—Scene title, used for the accessible label and the thumbnail corner label
childrenReactNode—Scene content — shown at full size on stage and scaled down as a thumbnail in the sidebar

How it works

  • Each scene binds the same shared element through layoutId; on a switch, the stage scene shrinks back into the sidebar while the selected thumbnail grows onto the stage, the two swapping in a synchronized FLIP.
  • The scene taking the stage focuses through a blur(14px) → blur(0) depth-of-field focus pull, while the sidebar thumbnails keep a slight blur and tilt to reinforce the depth.
  • Sidebar thumbnails scale the entire scene down with transform: scale(), giving a proportional "mini stage" preview rather than maintaining a separate set of thumbnail content.
  • When several StageManagerScenes coexist on one page, each one's LayoutGroup isolates its layoutIds, so scene ids never interfere with each other.

Accessibility

  • Sidebar thumbnails are native buttons, focusable with Tab and activated with Enter / Space; the ↑ / ↓ arrow keys (plus Home / End) rove focus among the thumbnails.
  • The stage is a role="region" carrying the current scene title as its aria-label; a separate aria-live="polite" region announces the current scene on a switch.
  • The mini preview inside a thumbnail is marked aria-hidden and is not interactive, so assistive technology only reads the button semantics "switch to scene: {label}".
  • When the user has "reduce motion" enabled at the system level, the movement, scaling, and blur all complete instantly and the switch result is shown directly.