KQ-2081 · WIPE/PREVIEW
Wipe Preview
An approval surface for an agent action that edits many records: every affected record is drawn twice in one grid, the result in flow and today's values laid over it, and a wipe decides which shows, with every changed field ringed solid on the result side and dashed on today's. The handle follows the pointer 1:1, rubber-bands past the ends and settles on springs.snap with the throw's velocity; approving runs the wipe to the result on springs.glide and an Applied stamp lands on springs.recoil once the host answers, while a refusal glides it back. The handle is a slider (arrows, Shift, Page keys, Home, End), the records are a multi-select listbox where X or Space skips the focused one, and below 28rem the wipe becomes a Before / After toggle.
Raise list prices on cold brew
Lift list prices about 7% to cover the new bean contract, round to .49 or .99, and retire sale prices the new price has caught up with.
9 items change by more than 10%.
Arrow keys move the wipe; Shift moves it further. In the list, Up and Down move between items and X or Space skips or includes the focused item.
wipe 50% · 38 of 40 included
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/wipe-preview
Props
- action
- WipeAction
- default defaultWipeAction
- The proposed action: { id, agent, title, summary, scope, proposedAt }.
- fields
- WipeField[]
- default defaultWipeFields
- The fields compared, in column order: { key, label, kind? } where kind is money, percent, number or text.
- records
- WipeRecord[]
- default defaultWipeRecords (40 Coldbrook items)
- The affected records: { id, title, meta?, before, after }.
- excluded / defaultExcluded
- string[]
- default — / []
- Ids left out of the action, controlled or initial.
- onExcludedChange
- (ids) => void
- default —
- Fires with every excluded id after an exclusion changes.
- onExclude
- (id, excluded) => void
- default —
- Fires from the key or press that skipped a record (true) or put it back (false).
- value / defaultValue
- number
- default — / 50
- The wipe position, 0 (all today) to 100 (all result), controlled or initial.
- onValueChange
- (value) => void
- default —
- Fires when a drag, key or toggle settles the wipe.
- onApprove
- (includedIds) => void | Promise
- default —
- Approve was pressed; a returned promise holds the stamp until it resolves, and a rejection slides the wipe back and states the reason.
- onReject
- (note) => void
- default —
- The action was sent back, with the reviewer's optional note.
- onEditPlan
- () => void
- default —
- Edit plan was pressed.
- onRetry
- () => void
- default —
- Retry simulation was pressed after a failure.
- largeChangeAt
- number
- default 10
- A record whose money or number field moves more than this percent counts as a large change and raises the warning.
- status
- "ready" | "loading" | "empty" | "failed"
- default "ready"
- Whether the simulation has produced records; failed shows the failure and holds Approve.
- failure
- { message, recordId? }
- default —
- Why the simulation failed and the record it stopped on.
- now
- number
- default Oct 17 2026, 14:00 UTC
- The moment ages are counted from, in ms.
- wipeStyle
- "line" | "feather" | "cells"
- default "line"
- The wipe's edge: a hard line, a soft 40px feather, or whole fields flipping as the handle passes each column.
- ringColor
- "amber" | "accent" | "signal" | "ink" | string
- default "amber"
- The ring around every changed field: a named colour or any CSS colour.
- accent
- "cobalt" | "plum" | "mint" | "ink" | string
- default "cobalt"
- The handle, Approve and the stamp: a named pigment or any CSS colour.
- formatMoney
- (amount) => string
- default Intl USD
- How money is written.
- height
- number
- default 560
- Tallest the surface grows, in px, before its record list scrolls.
- disabled
- boolean
- default false
- Read only: the wipe still compares, nothing can be decided.
- className
- string
- default —
- Classes for the surface.
| Prop | Type | Default | Description |
|---|---|---|---|
| action | WipeAction | defaultWipeAction | The proposed action: { id, agent, title, summary, scope, proposedAt }. |
| fields | WipeField[] | defaultWipeFields | The fields compared, in column order: { key, label, kind? } where kind is money, percent, number or text. |
| records | WipeRecord[] | defaultWipeRecords (40 Coldbrook items) | The affected records: { id, title, meta?, before, after }. |
| excluded / defaultExcluded | string[] | — / [] | Ids left out of the action, controlled or initial. |
| onExcludedChange | (ids) => void | — | Fires with every excluded id after an exclusion changes. |
| onExclude | (id, excluded) => void | — | Fires from the key or press that skipped a record (true) or put it back (false). |
| value / defaultValue | number | — / 50 | The wipe position, 0 (all today) to 100 (all result), controlled or initial. |
| onValueChange | (value) => void | — | Fires when a drag, key or toggle settles the wipe. |
| onApprove | (includedIds) => void | Promise | — | Approve was pressed; a returned promise holds the stamp until it resolves, and a rejection slides the wipe back and states the reason. |
| onReject | (note) => void | — | The action was sent back, with the reviewer's optional note. |
| onEditPlan | () => void | — | Edit plan was pressed. |
| onRetry | () => void | — | Retry simulation was pressed after a failure. |
| largeChangeAt | number | 10 | A record whose money or number field moves more than this percent counts as a large change and raises the warning. |
| status | "ready" | "loading" | "empty" | "failed" | "ready" | Whether the simulation has produced records; failed shows the failure and holds Approve. |
| failure | { message, recordId? } | — | Why the simulation failed and the record it stopped on. |
| now | number | Oct 17 2026, 14:00 UTC | The moment ages are counted from, in ms. |
| wipeStyle | "line" | "feather" | "cells" | "line" | The wipe's edge: a hard line, a soft 40px feather, or whole fields flipping as the handle passes each column. |
| ringColor | "amber" | "accent" | "signal" | "ink" | string | "amber" | The ring around every changed field: a named colour or any CSS colour. |
| accent | "cobalt" | "plum" | "mint" | "ink" | string | "cobalt" | The handle, Approve and the stamp: a named pigment or any CSS colour. |
| formatMoney | (amount) => string | Intl USD | How money is written. |
| height | number | 560 | Tallest the surface grows, in px, before its record list scrolls. |
| disabled | boolean | false | Read only: the wipe still compares, nothing can be decided. |
| className | string | — | Classes for the surface. |