KQ-1104 · PEEK/HOLD
Peek Hold
A list whose rows you can look into before you open them: a long press charges while the rest of the list starts to blur, then the row lifts out of the page on the snap spring and grows into a floating preview on the glide spring, with its actions beside it. Without letting go, sliding onto an action highlights it on a snap-spring pill and releasing chooses it; releasing on nothing cancels, and the card glides back down into its row, while a still release leaves the preview open. Right-click, the menu key and Shift+F10 open the same preview, and its actions are a menu driven by the arrow keys, Enter, Escape and Tab.
hold a row to peek · shift+f10 from the keyboard
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/peek-hold
Props
- items
- { id: string; title: string; subtitle?: string; meta?: string; leading?: ReactNode; badge?: ReactNode; preview: ReactNode }[]
- default —
- The rows. The row's own header becomes the top of its preview, and preview is revealed under it.
- menu
- PeekHoldAction[] | ((item: PeekHoldItem) => PeekHoldAction[])
- default —
- The actions offered under a preview ({ id, label, icon?, tone?: "default" | "danger" }), or a function of the item that picks them.
- onOpen
- (itemId: string) => void
- default —
- A plain tap or click on a row, or Enter or Space on it.
- onAction
- (actionId: string, itemId: string) => void
- default —
- An action chosen from a preview, by release, click or Enter. Fires before the preview closes.
- onPeekChange
- (itemId: string | null) => void
- default —
- A preview opened, with its item's id, or closed, with null.
- label
- string
- default —
- The list's accessible name.
- delay
- number
- default 450
- How long a press charges before the row lifts, in ms. The charge (the row sinking, the list blurring) runs exactly this long.
- lift
- number
- default 12
- How far the row rises as it comes free, in px; its scale and shadow grow with it, and 0 is a flat, in-place expansion.
- blur
- number
- default 6
- How hard the list behind a preview blurs, in px.
- actions
- "list" | "row"
- default "list"
- The actions as a vertical menu of icon and label, or as one row of icon-over-label buttons.
- sound
- boolean
- default false
- Play a swell as the row lifts, a tick as the highlight moves between actions, and a pop when one is chosen. Nothing plays, and no audio context exists, unless this is on.
- disabled
- boolean
- default false
- Dims the list, disables its rows and closes any preview.
- className
- string
- default —
- Merged onto the root's classes.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | { id: string; title: string; subtitle?: string; meta?: string; leading?: ReactNode; badge?: ReactNode; preview: ReactNode }[] | — | The rows. The row's own header becomes the top of its preview, and preview is revealed under it. |
| menu | PeekHoldAction[] | ((item: PeekHoldItem) => PeekHoldAction[]) | — | The actions offered under a preview ({ id, label, icon?, tone?: "default" | "danger" }), or a function of the item that picks them. |
| onOpen | (itemId: string) => void | — | A plain tap or click on a row, or Enter or Space on it. |
| onAction | (actionId: string, itemId: string) => void | — | An action chosen from a preview, by release, click or Enter. Fires before the preview closes. |
| onPeekChange | (itemId: string | null) => void | — | A preview opened, with its item's id, or closed, with null. |
| label | string | — | The list's accessible name. |
| delay | number | 450 | How long a press charges before the row lifts, in ms. The charge (the row sinking, the list blurring) runs exactly this long. |
| lift | number | 12 | How far the row rises as it comes free, in px; its scale and shadow grow with it, and 0 is a flat, in-place expansion. |
| blur | number | 6 | How hard the list behind a preview blurs, in px. |
| actions | "list" | "row" | "list" | The actions as a vertical menu of icon and label, or as one row of icon-over-label buttons. |
| sound | boolean | false | Play a swell as the row lifts, a tick as the highlight moves between actions, and a pop when one is chosen. Nothing plays, and no audio context exists, unless this is on. |
| disabled | boolean | false | Dims the list, disables its rows and closes any preview. |
| className | string | — | Merged onto the root's classes. |