KQ-1489 · FOLDER/FAN
Folder Fan
A folder that fans its papers out to say hello: hovering or focusing it lifts the papers out, each rising and tilting about its foot by a seeded share of the fan angle with a soft shadow, front paper first on springs.snap. Opening it swings the front flap down about its hinge in perspective on springs.snap and sends the papers out into a list beside it — each gliding from its fan pose to its row on springs.glide, unrotating and widening into a row with the document's name, in a cascade — and choosing a row folds the list back into the folder with the chosen paper left peeking out of the top. The folder is a button that opens a listbox: Enter, Space or ArrowDown open it, arrows move, Enter or Space chooses and Escape closes.
statements · hover or press to open
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/folder-fan
Props
- items
- { id: string; label: string; meta?: string }[]
- default —
- The documents in the folder, first on top; the first `sheets` of them are shown.
- value / defaultValue
- string | null
- default — / null
- The chosen document's id, controlled or uncontrolled. The chosen paper peeks out of the closed folder.
- onValueChange
- (id: string) => void
- default —
- Fires from the click or key that chose a document.
- open / defaultOpen
- boolean
- default — / false
- Whether the folder is open, controlled or uncontrolled.
- onOpenChange
- (open: boolean) => void
- default —
- Fires from the press, key, choice or outside click that opened or closed it.
- label
- string
- default "Documents"
- The folder's name, shown beside it, and its accessible name (with the chosen document).
- sheets
- number
- default 4
- How many papers it holds — the first `sheets` items — 1 to 8.
- fan
- number
- default 24
- The fan's total spread when the papers lift, in degrees.
- lift
- number
- default 18
- How far the papers rise out of the folder on hover and focus, in px.
- color
- "manila" | "sky" | "sage" | "clay" | string
- default "manila"
- The folder's stock: a named pigment at fixed lightness, or any CSS colour.
- size
- "sm" | "md" | "lg"
- default "md"
- Max width (280, 320 or 360px), folder and row size.
- sound
- boolean
- default false
- Play a paper slide per sheet as the list spreads, a crisper one on choose and a soft one on close; only in answer to a press or key.
- disabled
- boolean
- default false
- Disables the folder: no fan, no list.
- className
- string
- default —
- Classes for the root, whose height glides between the closed folder and the open list.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | { id: string; label: string; meta?: string }[] | — | The documents in the folder, first on top; the first `sheets` of them are shown. |
| value / defaultValue | string | null | — / null | The chosen document's id, controlled or uncontrolled. The chosen paper peeks out of the closed folder. |
| onValueChange | (id: string) => void | — | Fires from the click or key that chose a document. |
| open / defaultOpen | boolean | — / false | Whether the folder is open, controlled or uncontrolled. |
| onOpenChange | (open: boolean) => void | — | Fires from the press, key, choice or outside click that opened or closed it. |
| label | string | "Documents" | The folder's name, shown beside it, and its accessible name (with the chosen document). |
| sheets | number | 4 | How many papers it holds — the first `sheets` items — 1 to 8. |
| fan | number | 24 | The fan's total spread when the papers lift, in degrees. |
| lift | number | 18 | How far the papers rise out of the folder on hover and focus, in px. |
| color | "manila" | "sky" | "sage" | "clay" | string | "manila" | The folder's stock: a named pigment at fixed lightness, or any CSS colour. |
| size | "sm" | "md" | "lg" | "md" | Max width (280, 320 or 360px), folder and row size. |
| sound | boolean | false | Play a paper slide per sheet as the list spreads, a crisper one on choose and a soft one on close; only in answer to a press or key. |
| disabled | boolean | false | Disables the folder: no fan, no list. |
| className | string | — | Classes for the root, whose height glides between the closed folder and the open list. |