KQ-1883 · ROOM/WITHIN

Room Within

A story told as one long zoom: the stage is its own scroll container, each picture holds an opening exactly the stage's shape, and scrolling zooms into it until it fills the stage and becomes the next picture, which holds the next opening. The camera is one transform written straight from the scroll — a pure geometric scale about the opening's fixed point, so it grows from one steady spot and every level boundary is seamless — while the glass sheen slides off the window, the far room's haze lifts and the captions cross-fade with the zoom; a click on the opening, the depth gauge or Page Down travels there on springs.drift. Page Down, Space and Enter go in a level, Page Up, Shift+Space and Backspace come back out, Home and End jump to the ends.

KQ-1883 · ROOM/WITHIN

Fernworks Editions · Issue 12

Five rooms, one window

Each picture holds the next one. Scroll, or press Page Down, Space or Enter, to go in through the opening; Page Up, Shift and Space, or Backspace to come back out. Home and End go to the first and last picture. Now showing The reading room.

level 1 of 5 · The reading room · scroll or page down

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/room-within

Props

items
RoomWithinLevel[]
default defaultRoomWithinLevels
The pictures, outermost first, each { id?, src?, alt, caption?, detail?, art?, window? }; each one's opening holds the next.
depth
number
default 5
How many levels deep the story goes, 2 to 6 (and no more than items).
frame
"window" | "gilt" | "mat" | "none"
default "window"
How each opening is framed: a painted casement with a sill, a gilt frame, a paper mat, or a seamless cut.
easing
"linear" | "dwell" | "snap"
default "dwell"
How scrolling maps to the zoom: steady, holding each picture still for a beat, or snapping every scroll to a picture.
value / defaultValue
number
default — / 0
The level shown. A new controlled value travels there.
onValueChange
(level: number) => void
default —
Fires from the scroll, key or click that brought a new level nearest, with that level.
scrollLength
number
default 1.2
Scroll for one level, as a share of the stage's height, 0.5 to 3.
loop
boolean
default true
The deepest picture's opening holds the first room again.
captions
boolean
default true
Show each level's caption and detail over the picture.
rail
boolean
default true
Show the depth gauge on the right edge; its ticks travel to a level.
hint
boolean
default true
On first view the camera leans a little way into the window and back, and a cue says to scroll.
height
number | string
default 420px
The stage's height: px, or any CSS length. A className height works too.
label
string
default "Room within"
The story's accessible name.
disabled
boolean
default false
No scrolling, keys or clicks; the stage dims.
className
string
default —
Classes for the stage.