KQ-1846 · PETRI/STACK
Petri Stack
A gallery as a tilted stack of glass petri dishes in real CSS 3D, each holding its picture like a specimen under a lid, with thin stacked rims, a glass tint, a soft shadow between layers and refraction at the rim where the picture bends into the glass. A click, a key or a flick sends the top dish off: it lifts and slides out on springs.glide with the flick's velocity, drops while the rest of the stack rises a level in a cascade, and tucks in underneath to land on springs.recoil with a glassy clack, bringing the next picture up; hovering or keyboard focus lifts the top lid on springs.snap. The stack is a focusable carousel where Right, Down, Enter and Space send the top dish down, Left and Up bring the bottom one back, Home and End jump, and a drag follows 1:1 and commits by projection.
Fieldline Lab · culture log
This week’s plates
Click or press Right to send the top dish to the bottom; Left brings the bottom dish back up. Home and End go to the first and last. You can also drag the top dish aside.
colony 14 · 1 of 6 · clear glass
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/petri-stack
Props
- items
- PetriItem[]
- default defaultPetriItems
- The dishes, top first: { src?, alt, caption?, art? }; without src or art a specimen is drawn in code.
- value / defaultValue
- number
- default 0
- The dish on top; controlled or initial.
- onValueChange
- (index: number) => void
- default —
- Fires from the click, key or drag that changed the top dish, with its index.
- tilt
- number
- default 55
- How far the stack leans back from you, 10 to 75 degrees: low looks down on it, high sees it side on.
- gap
- number
- default 12
- Air between one dish and the next, px, 2 to 32.
- glass
- "clear" | "sea" | "amber" | "smoke"
- default "clear"
- The glass's tint.
- visible
- number
- default 5
- How many dishes show in the stack, 2 to 7; the rest wait unseen beneath.
- lift
- number
- default 8
- How far hovering or focus lifts the top lid, px.
- refraction
- number
- default 0.6
- How strongly the glass bends the picture at the rim, 0 to 1.
- height
- number
- default 232
- Height of the stage, px; the dishes size themselves to fit it and the width.
- sound
- boolean
- default false
- Play the glassy clack as a dish lands. Off unless asked for.
- label
- string
- default "Specimens"
- The stack's accessible name.
- disabled
- boolean
- default false
- No clicks, keys or drags.
- className
- string
- default —
- Classes for the root.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | PetriItem[] | defaultPetriItems | The dishes, top first: { src?, alt, caption?, art? }; without src or art a specimen is drawn in code. |
| value / defaultValue | number | 0 | The dish on top; controlled or initial. |
| onValueChange | (index: number) => void | — | Fires from the click, key or drag that changed the top dish, with its index. |
| tilt | number | 55 | How far the stack leans back from you, 10 to 75 degrees: low looks down on it, high sees it side on. |
| gap | number | 12 | Air between one dish and the next, px, 2 to 32. |
| glass | "clear" | "sea" | "amber" | "smoke" | "clear" | The glass's tint. |
| visible | number | 5 | How many dishes show in the stack, 2 to 7; the rest wait unseen beneath. |
| lift | number | 8 | How far hovering or focus lifts the top lid, px. |
| refraction | number | 0.6 | How strongly the glass bends the picture at the rim, 0 to 1. |
| height | number | 232 | Height of the stage, px; the dishes size themselves to fit it and the width. |
| sound | boolean | false | Play the glassy clack as a dish lands. Off unless asked for. |
| label | string | "Specimens" | The stack's accessible name. |
| disabled | boolean | false | No clicks, keys or drags. |
| className | string | — | Classes for the root. |