KQ-1878 · FILING/TRAY
Filing Tray
A scroll-linked stack: inside whatever scrolls it, each card slides up and files itself onto a tray near the top, and as the next card slides over it the filed card tilts a little to one side, sinks a hair and dims, so a small untidy pile grows above the card being read, every older card's top edge peeking above the next while the tray's label counts the pile. Each card's cover depth is measured from the scroll and the shown depth follows it on a critically damped spring with the springs.glide constants, so tilts settle like paper a breath behind the scroll, and a landing card presses the pile on the springs.recoil constants. Scrolling back lifts the cards off in order; Tab or Arrow Down moves to the next card and files the one before, Arrow Up lifts it back.
Fieldline · Survey log
Coldbrook estuary, day 3
Eight notes from the morning tide. Scroll to file them.
- 05:50TideGauge read 0.4 m at slack. The flats are open to the second marker; the channel holds a thin silver line.
- 06:15Birds
Curlew on the north flat
Eleven curlew feeding in a loose line, moving upstream with the edge of the water. - 06:40Gear
Logger 3 swapped
Battery at 12%. The new logger is set to ten-minute intervals, sealed and tied to the post at knee height. - 07:05Water
Salinity transect
Five samples from the footbridge to the reed bed: 31, 29, 24, 17 and 9 ppt. - 07:20Birds
Heron count
Four grey herons at the weir, one juvenile. Two left when the dog walkers came through. - 07:45Tide
Flood begins
Water turning at the bar. The flats cover from the seaward side, fastest near the creek mouths. - 08:10Gear
Camera trap check
Card full: 212 frames overnight. A fox twice, an otter once at 03:12, the rest wind in the grass. - 08:30Notes
Packed up
All three loggers running. Back for the 14:00 low water to read the transect again.
Each card files itself on the pile as you scroll past it. Tab or Arrow Down moves to the next card and files the one before; Arrow Up lifts it back.
End of the morning log. The afternoon round starts at 14:00.
filed 0 of 8 · reading 05:50 low water at the bar
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/filing-tray
Props
- cards
- { id: string; title: string; body?: ReactNode; meta?: string; tag?: string }[]
- default defaultFilingCards
- The cards, in reading order.
- tilt
- number
- default 3
- How far a filed card tilts, 0 to 8 degrees, alternating sides: a square stack to a loose pile.
- fade
- number
- default 0.45
- How far a filed card dims as more land on it, 0 to 1.
- offset
- number
- default 8
- How much of each filed card's top edge peeks above the next, 0 to 16 px.
- inset
- number
- default 34
- Where the first filed card sticks, px below the top of the scroll container; the tray's label sits above it.
- maxDepth
- number
- default 5
- How many filed cards keep peeking; deeper ones sink out of sight.
- gap
- number
- default 16
- Space between cards that are still to be read, px.
- settle
- boolean
- default true
- A card that lands presses the pile and settles with a small bounce.
- tray
- boolean
- default true
- Draw the tray behind the pile, with its count on a label strip.
- trayLabel
- string
- default "Filed"
- The word on the tray's label before the count.
- seed
- number
- default 1
- Seeds which way and how far each card tilts.
- headingLevel
- 2 | 3 | 4 | 5 | 6
- default 3
- Heading level of the card titles.
- onFiledChange
- (count: number) => void
- default —
- Fires from the scroll that filed or lifted a card, with how many are filed.
- label
- string
- default "Filing tray"
- The stack's accessible name.
- className
- string
- default —
- Classes for the root; it takes the width of its column.
| Prop | Type | Default | Description |
|---|---|---|---|
| cards | { id: string; title: string; body?: ReactNode; meta?: string; tag?: string }[] | defaultFilingCards | The cards, in reading order. |
| tilt | number | 3 | How far a filed card tilts, 0 to 8 degrees, alternating sides: a square stack to a loose pile. |
| fade | number | 0.45 | How far a filed card dims as more land on it, 0 to 1. |
| offset | number | 8 | How much of each filed card's top edge peeks above the next, 0 to 16 px. |
| inset | number | 34 | Where the first filed card sticks, px below the top of the scroll container; the tray's label sits above it. |
| maxDepth | number | 5 | How many filed cards keep peeking; deeper ones sink out of sight. |
| gap | number | 16 | Space between cards that are still to be read, px. |
| settle | boolean | true | A card that lands presses the pile and settles with a small bounce. |
| tray | boolean | true | Draw the tray behind the pile, with its count on a label strip. |
| trayLabel | string | "Filed" | The word on the tray's label before the count. |
| seed | number | 1 | Seeds which way and how far each card tilts. |
| headingLevel | 2 | 3 | 4 | 5 | 6 | 3 | Heading level of the card titles. |
| onFiledChange | (count: number) => void | — | Fires from the scroll that filed or lifted a card, with how many are filed. |
| label | string | "Filing tray" | The stack's accessible name. |
| className | string | — | Classes for the root; it takes the width of its column. |