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