KQ-1683 · BATCH/RUNNER

Batch Runner

A bulk-action dialog that confirms its scope as one small cell per item, then runs inside itself: a soft band glides down the grid a row at a time on springs.glide while each cell under it is stamped done on springs.flick, so every row reads as a ripple, and failures fill red with their reason and never bounce. Escape pauses after the item in flight, Stop leaves the rest untouched, and finishing folds the live counts into one plain sentence with the failures grouped by reason; Retry failed reruns only the red cells. The action is a roving radiogroup and the cells a role="grid" with one tab stop, arrows, Home/End and Page keys.

KQ-1683 · BATCH/RUNNER

248 selected · confirm to run

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/batch-runner

Props

items
BatchItem[]
default defaultBatchItems
The selection, in reading order: { id, label, detail?, error?, recovers? } (error and recovers drive the built-in simulation only).
actions
BatchAction[]
default defaultBatchActions
The actions in the picker: { id, label, past, progressive, description, icon?, targetLabel?, targets? }.
action / defaultAction
string
default — / first action
The chosen action, controlled or initial.
onActionChange
(action: string) => void
default —
Fires from the press or key that picked another action.
run
(item, { action, target, attempt }) => void | Promise<void>
default simulated
The work for one item, called one at a time in reading order; a throw or rejection fails it with the error's message as its reason.
pace
number
default 24
Milliseconds per item for the built-in simulation; a retry takes at least 280ms per item so each can be seen.
autoStart
boolean
default false
Start the run by itself the first time the dialog scrolls into view.
itemLabel
{ one: string; other: string }
default { one: "conversation", other: "conversations" }
What one item is called, in titles, counts and the summary.
source
string
default "From Open · Coldbrook Support"
Where the selection came from, under the title.
onRun
({ action, target, ids }) => void
default —
The primary press started the run.
onRetry
(ids: string[]) => void
default —
Retry failed was pressed, with the ids it reruns.
onCancel
(progress: { done, failed, left }) => void
default —
Cancel (before the run) or Stop (during it) was pressed.
onPauseChange
(paused: boolean) => void
default —
The run paused (Escape or Pause) or resumed.
onProgress
(progress: { done, failed, left }) => void
default —
Fires as each item lands, with counts across the whole selection.
onComplete
(summary: BatchSummary) => void
default —
A pass finished or stopped: totals, failures grouped by reason, and whether it was cancelled.
onClose
() => void
default —
Done was pressed, or Escape on the summary.
cellShape
"square" | "round" | "bar"
default "square"
Rounded squares, dots, or tall tally bars that fold the selection into fewer, taller rows.
cellSize
number
default 11
The largest cell edge in px; cells shrink below it to keep the grid under maxGridHeight.
palette
"cobalt" | "moss" | "graphite" | "dusk"
default "cobalt"
The done pigment, the row band and the progress line; failures stay red in every palette.
maxGridHeight
number
default 200
Tallest the grid may grow, px, before its cells shrink to fit.
status
"ready" | "loading" | "error"
default "ready"
Loading shows breathing placeholder cells and holds the primary; error offers Try again.
onReload
() => void
default —
Try again was pressed after the selection 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 started, paused or retried.
className
string
default —
Classes for the dialog panel.