import{ScrollExpand}from"@/components/ui/scroll-expand"functionPlate({small=false}:{small?:boolean}){return(<divclassName="grid gap-(--ot-space-5) py-(--ot-space-6)"><pclassName={small?"ot-f":"ot-fff"}style={{margin:0}}>Space<br/>does the<br/>layout.</p><pclassName="ot-pp max-w-[18rem] justify-self-end text-pretty"style={{margin:0,color:"var(--ot-pencil)"}}>A hairline appears only where space alone can’t hold two things apart.</p></div>)}exportdefaultfunctionExample(){return(<divclassName="grid w-full gap-(--ot-space-9)"><pclassName="ot-pp"style={{margin:0,color:"var(--ot-pencil)"}}>Scroll down: the plates open as far as you go, and close when you go back.</p><ScrollExpandcaption={["Plate 01","Principles, the first"]}><Plate/></ScrollExpand><ScrollExpandvariant="horizon"caption={["Plate 02","From the horizon"]}><Plate/></ScrollExpand></div>)}
Contract
Underneath: native, plus a hook that reads the scroll from the real layout; made of corners and meta.
Anatomy: <figure class="ot-expand" data-variant="horizon"> holding .ot-expand-frame (a ot-corners) round .ot-expand-plate (the content), then figcaption.ot-expand-caption with a ot-meta row: the caption's words, then .ot-expand-share (aria-hidden). The hook sets --p, 0 to 1.
mark (the default): after the printer's crop marks and the frame of SHAPES / GRADIENTS. The plate is cropped (a clip-path) to a small square in the middle (--ot-expand-mark, --ot-space-8), and the four corner marks, --ot-space-4 long, stand a step (--ot-space-2) outside the crop, as crop marks stand outside the trim. As the page scrolls the crop opens to the whole plate. The caption's row is as wide as the crop (never narrower than 20rem or its space), so its hairlines draw out as it opens, the rule that carries the date and the name; the row ends on the share of the measure the crop has reached, in pencil tabular figures (0.42), as SPECTRA sets 0.13.
Scrubbed: --p is 0 as the plate's top comes in at the foot of the view and 1 once its middle is at the middle of the view (or as far as the page can scroll). It is read from the real layout in a frame asked for by the scroll event, which runs after a smooth scroller (Lenis) has moved the page, so the crop and the page move in the same frame. Nothing eases: it stops when you stop and closes when you scroll back. progress pins it.
horizon: after Eclipse, the disc standing on one line. The crop starts as a hairline across the whole measure (the horizon, drawn in --ot-rule-strong while it's shut, and gone by a quarter open) and opens up and down from it; the caption stays full width.
The whole plate is in the flow and read from the start; only the view of it is cropped. Nothing to focus. Reduced motion, or no script: it stands open. It is symmetric, so right to left changes nothing. Forced colours: the marks and the horizon in CanvasText.
Props
Props of Scroll expand
Prop
Type
Default
What it does
children
ReactNode
What the plate holds. It is all in the flow and read from the start; only the view of it is cropped.
caption
ReactNode | ReactNode[]
The words of the meta row under the plate, held apart by hairlines. The row is as wide as the crop, so its hairlines draw out as it opens; the share of the measure reached (0.42) closes it, in pencil.
variant
"mark" | "horizon"
"mark"
mark: the crop opens from a small square in the middle to the whole plate, its corner marks a step outside it like a printer's crop marks. horizon: after Eclipse; the crop starts as a hairline across the whole measure and opens up and down from it, the line fading as it goes.
progress
number
Pins how far it has opened, 0 to 1, instead of following the scroll.
--ot-expand-mark
CSS length
var(--ot-space-8)
The size of the mark it opens from.
Craft
Where its move comes from
Where its move comes from
Component
Reference
Move
Scroll expand
The printer's crop marks; SHAPES / GRADIENTS frame
Crop marks open from a small mark to the measure as you scroll; the caption's rule draws out with them
Horizon scroll expand
Eclipse
The plate opens up and down from a hairline horizon
How it moves
How it moves
Component
Articulation
What moves
Scroll expand
Rubato (the reader's tempo)
The crop and its marks open only as far as the scroll has gone, forwards or back