KQ-1684 · PLATE/PICKER

Plate Picker

An asset picker dialog for choosing several images in order: picking a plate lands a numbered badge on it on springs.recoil while a copy of the picture flies from the tile into its slot in the tray on springs.glide, and dropping one makes every later badge roll its digit down on springs.snap while the tray closes the gap on glide. The tray reorders by drag — the thumb follows the finger 1:1, neighbours glide aside, the drop snaps home with the release velocity — or by Shift with an arrow, and tabs switch between the library (folders over plates drawn in code), uploads whose veil lifts with their progress, and links. The grid is a multiselectable role="grid" with one roving cell; Space or Enter picks.

KQ-1684 · PLATE/PICKER

3 chosen · salt flat at dusk first

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/plate-picker

Props

assets
PlateAsset[]
default defaultPlateAssets
Every plate: { id, name, folder, width?, height?, src?, art?, status?, progress?, error? }; without src a plate is drawn in code from art (or its id).
folders
PlateFolder[]
default defaultPlateFolders
The folders, in order: { id, name }; "All" is added in front.
folder / defaultFolder
string
default — / "all"
The folder shown, controlled or initial ("all" for every folder).
onFolderChange
(folder: string) => void
default —
Fires from the chip or key that changed the folder.
selected / defaultSelected
string[]
default — / []
The chosen plate ids in insert order, controlled or initial.
onSelect
(ids: string[]) => void
default —
Fires from every pick, removal and reorder with the ids in order.
max
number
default 6
How many plates may be chosen; past it the unpicked plates dim and say why.
onUpload
(file, report) => Promise<void | Partial<PlateAsset>>
default simulated
Uploads one file; call report(0–1) as it goes; resolve (optionally with fields to merge) or reject with the reason the tile shows.
onLink
(url: string) => void | Promise<void>
default —
An https address was added from the Link tab; reject to refuse it with a reason. Nothing is fetched.
onInsert
(assets: PlateAsset[]) => void
default —
Insert was pressed, with the chosen plates in order.
onCancel
() => void
default —
Cancel, the close button or Escape.
tab / defaultTab
"library" | "upload" | "link"
default — / "library"
The tab shown, controlled or initial.
onTabChange
(tab) => void
default —
Fires from the tab press or key that changed the tab.
columns
number
default 4
Grid columns at full width; containers under 30rem always use two.
badgeStyle
"disc" | "tab" | "frame"
default "disc"
The pick number as a disc on the corner, a folded corner tab, or a thick frame with the number in its corner.
accent
string
default "var(--accent-bright)"
Badges, the selection ring, the tray's numbers and the tab indicator; filled badges take its hue at a fixed lightness.
title
string
default "Choose plates"
The dialog's heading and accessible name.
subtitle
string
default "Fieldline · Issue 14, Tidelines"
A quiet line under the heading.
itemLabel
{ one: string; other: string }
default { one: "plate", other: "plates" }
What one asset is called, in counts and on the Insert button.
height
number
default 540
Dialog height in px; the grid scrolls inside it.
status
"ready" | "loading" | "error"
default "ready"
Loading shows breathing placeholder tiles; error offers Try again.
onReload
() => void
default —
Try again was pressed after the library failed to load.
modal
boolean
default false
Trap Tab inside the dialog and set aria-modal; pass it when you render it in an overlay.
disabled
boolean
default false
Nothing can be picked, uploaded or inserted.
className
string
default —
Classes for the dialog panel.