KQ-1286 · PUSH/SHEET

Push Sheet

A bottom sheet that pushes its page back: as the sheet rises on springs.glide, the page behind scales down about its top centre, drops a few pixels, rounds its corners and dims like a card behind another in a stack, and a sheet opened from a sheet steps the one beneath it back the same way. Every layer's look is a function of how far the sheets above it have risen, so the grabber and title bar drag the top sheet 1:1 with everything behind following, rubber-banded past the top stop, and a release projects the throw to the nearest stop (half and full by default) carried on glide with its velocity, or sends the sheet away at its own speed. Each sheet is a modal dialog with focus moved in and trapped, Escape closes it and returns focus to its opener, and its grabber is a slider whose arrows move between stops.

KQ-1286 · PUSH/SHEET

Waylight Pay

DJ

Available

£2,480.16

Coldbrook Bank ·· 4417

Recent

  • Basinworks CoffeeToday, 08:14−£4.20
  • From Tomas ReyesYesterday+£36.00
  • Fieldline RailMon−£12.80
  • Gaugeworks MarketSun−£61.45

nothing open · press send

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/push-sheet

Props

sheets
PushSheetItem[]
default —
Every sheet that can open: id, title, description, content (a node or a function of the stack's controls) and optional snaps of its own.
children
React.ReactNode | ((api: PushSheetApi) => React.ReactNode)
default —
The page under the sheets. As a function it receives { open, close, snapTo, stack }.
value / defaultValue
string[]
default []
The open sheets' ids, bottom first, controlled or initial (at most four).
onValueChange
(stack: string[]) => void
default —
Fires from the call, drag, key or button that opened or closed a sheet, with the new stack.
onSnapChange
(id: string, snap: number) => void
default —
A sheet came to rest on a stop after a drag, a key or snapTo, given as a share of its full height.
push
number
default 0.6
How far a covered layer steps back, 0 to 1: 0 only dims it; 1 shrinks it 6% per level, drops it 16px and rounds it fully.
snaps
"half-full" | "full" | "thirds" | number[]
default "half-full"
Where a sheet stops: half and full height, full only, thirds, or your own shares of the full height.
dim
number
default 0.35
How dark a fully covered layer gets, 0 to 0.8; a second level darkens it by half again.
openAt
"lowest" | "highest"
default "lowest"
Where a new sheet comes to rest.
inset
number
default 28
The gap above a sheet at full height, in px, where the layer behind peeks out.
width
number
default 560
A sheet's widest, in px; it is centred when the box is wider.
radius
number
default 16
The sheets' top corners and the pushed page's corners, in px.
dismissible
boolean
default true
Whether a drag down, Escape, a press on the page behind and ArrowDown at the lowest stop close the top sheet.
height
number | string
default 520
The box's height, in px or any CSS length; everything stays inside it.
backdrop
string
default "color-mix(in oklab, var(--background) 45%, black)"
Any CSS colour shown behind the pushed page.
closeLabel
string
default "Close"
The close button's accessible name.
sound
boolean
default false
A swish as a sheet opens or is sent away, and a thock when it lands on a stop, louder for a harder throw and lower for a higher stop.
disabled
boolean
default false
Ignores opens, drags and keys and dims the box.
className
string
default —
Classes for the root element.