KQ-1567 · BOOK/SPINES
Book Spines
Pictures shelved as books whose jackets wrap round their spines, so each spine shows a sliver of its picture under a vertical title. Resting on a spine or focusing it tips the book out of the row toward you on springs.snap and turns it on its own axis, a real CSS 3D box, to show the whole picture on its cover on springs.glide, its cover left a few degrees ajar; the neighbours lean into the gap on springs.snap, the lean running down the row. Arrow keys browse and open each book, Home and End jump, Enter holds a book open and Escape puts it back; a shelf wider than its box drags 1:1, rubber-bands and settles on springs.glide.
Waylight Press · autumn list
Twenty photo books
Arrow keys move along the shelf and open each book; Enter holds a book open and Escape puts it back.
held open · 5 of 20 · Dune Sea
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/book-spines
Props
- items
- { src?: string; alt: string; caption?: string }[]
- default twenty drawn books
- The books, one picture each, up to 40; the caption is the title on the spine and cover.
- spineWidth
- number
- default 22
- Width of each spine in px, 14 to 36: wider spines show more of their picture.
- lean
- number
- default 0.6
- How far the neighbours lean into the gap, 0 (upright) to 1 (tops meet).
- shelf
- "oak" | "walnut" | "slate" | "glass"
- default "oak"
- The shelf's finish.
- value / defaultValue
- number | null
- default null
- The book held open, controlled or initial.
- onValueChange
- (index: number | null) => void
- default —
- Fires from the click or key that held a book open or let it go.
- openOn
- "hover" | "click"
- default "hover"
- What opens a book under a pointer; focus always opens.
- delay
- number
- default 90
- How long the pointer rests on a spine before it opens, ms.
- tip
- number
- default 8
- How far an opening book tips toward you, degrees.
- coverRatio
- number
- default 0.7
- Cover width as a share of the book's height, 0.55 to 0.85.
- bookHeight
- number
- default fitted
- The tallest book, px.
- titles
- boolean
- default true
- Set the titles on the spines.
- seed
- number
- default 1
- Seeds the books' heights and spine widths.
- label
- string
- default "Bookshelf"
- The shelf's accessible name.
- disabled
- boolean
- default false
- No opening, holding or scrolling.
- className
- string
- default —
- Sizes the shelf; it fills its parent by default (h-full w-full).
| Prop | Type | Default | Description |
|---|---|---|---|
| items | { src?: string; alt: string; caption?: string }[] | twenty drawn books | The books, one picture each, up to 40; the caption is the title on the spine and cover. |
| spineWidth | number | 22 | Width of each spine in px, 14 to 36: wider spines show more of their picture. |
| lean | number | 0.6 | How far the neighbours lean into the gap, 0 (upright) to 1 (tops meet). |
| shelf | "oak" | "walnut" | "slate" | "glass" | "oak" | The shelf's finish. |
| value / defaultValue | number | null | null | The book held open, controlled or initial. |
| onValueChange | (index: number | null) => void | — | Fires from the click or key that held a book open or let it go. |
| openOn | "hover" | "click" | "hover" | What opens a book under a pointer; focus always opens. |
| delay | number | 90 | How long the pointer rests on a spine before it opens, ms. |
| tip | number | 8 | How far an opening book tips toward you, degrees. |
| coverRatio | number | 0.7 | Cover width as a share of the book's height, 0.55 to 0.85. |
| bookHeight | number | fitted | The tallest book, px. |
| titles | boolean | true | Set the titles on the spines. |
| seed | number | 1 | Seeds the books' heights and spine widths. |
| label | string | "Bookshelf" | The shelf's accessible name. |
| disabled | boolean | false | No opening, holding or scrolling. |
| className | string | — | Sizes the shelf; it fills its parent by default (h-full w-full). |