KQ-2072 · MERGE/TRAIN
Merge Train
A merge queue drawn as a train: the pull requests agents have opened are coupled cars on a line through the depot and the stations for tests, review and merge. When a car clears a station the train advances on springs.glide, the front car first and each car behind a cascade later like slack running out, a car that fails uncouples and drops onto the siding on springs.recoil while the cars behind close the gap, and a merged car pulls away on the exit ease; couplers latch on springs.flick and check pips fill as checks pass. Below 30rem the line runs down the page. The cars are a listbox: arrows walk the line, Enter opens a car's checks, Delete pulls it from the train and Alt with an arrow moves a waiting car in the queue.
Merge train
waylight/app · main
6 in train · 0 merged
Arrow keys move between cars. Enter opens a car, Delete pulls it from the train, Alt with an arrow moves a waiting car in the queue.
tests, review, merge · 6 changes · 6 in train · 0 merged
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/merge-train
Props
- changes
- TrainChange[]
- default defaultTrainChanges
- Every car in a stable order: { id, number, title, agent, branch?, stop, result, checks?, progress?, failedReason? }. stop is -1 in the depot.
- stations
- TrainStation[]
- default defaultTrainStations
- The stops after the depot, in order: { id, label }.
- order / defaultOrder
- string[]
- default — / the depot cars in changes order
- The queue order of the cars waiting in the depot, next to leave first.
- onReorder
- (order) => void
- default —
- Fires from Alt+Arrow or the Move buttons with the new queue order.
- open / defaultOpen
- string | null
- default — / null
- The car whose checks are open below the yard.
- onOpenChange
- (id) => void
- default —
- Fires from Enter, a click, Escape or Close with the open car or null.
- onRetry
- (change) => void
- default —
- Retry was pressed on a car standing on the siding.
- onRemoveCar
- (change) => void
- default —
- Delete, Backspace or Remove pulled a car from the train; it leaves at once.
- held
- boolean
- default false
- Hold the train: the last station's lamp turns to stop and a banner says why.
- heldReason
- string
- default "main is frozen for the 4.2 release"
- Why the train is held.
- merged
- number
- default 0
- Changes merged so far today, for the header.
- status
- "running" | "loading" | "empty" | "error"
- default "running"
- Whether the train's data has arrived; an empty train draws an empty depot.
- onReload
- () => void
- default —
- Try again was pressed after the train failed to load.
- title
- string
- default "Merge train"
- The heading and the listbox's name.
- subtitle
- string
- default "waylight/app · main"
- Under the heading.
- carStyle
- "card" | "pill" | "boxcar"
- default "card"
- A card with its checks, a compact pill, or a boxcar with a roof band and wheels.
- trackStyle
- "rails" | "transit" | "ruled"
- default "rails"
- Rails and sleepers, one transit line with station rings, or a dashed hairline.
- accent
- "cobalt" | "plum" | "mint" | "ink" | string
- default "cobalt"
- Running cars, progress and the open car: a named pigment or any CSS colour.
- disabled
- boolean
- default false
- Read only: cars can be walked and read but not opened, moved or removed.
- className
- string
- default —
- Classes for the surface; it caps at 36rem tall and its body scrolls inside.
| Prop | Type | Default | Description |
|---|---|---|---|
| changes | TrainChange[] | defaultTrainChanges | Every car in a stable order: { id, number, title, agent, branch?, stop, result, checks?, progress?, failedReason? }. stop is -1 in the depot. |
| stations | TrainStation[] | defaultTrainStations | The stops after the depot, in order: { id, label }. |
| order / defaultOrder | string[] | — / the depot cars in changes order | The queue order of the cars waiting in the depot, next to leave first. |
| onReorder | (order) => void | — | Fires from Alt+Arrow or the Move buttons with the new queue order. |
| open / defaultOpen | string | null | — / null | The car whose checks are open below the yard. |
| onOpenChange | (id) => void | — | Fires from Enter, a click, Escape or Close with the open car or null. |
| onRetry | (change) => void | — | Retry was pressed on a car standing on the siding. |
| onRemoveCar | (change) => void | — | Delete, Backspace or Remove pulled a car from the train; it leaves at once. |
| held | boolean | false | Hold the train: the last station's lamp turns to stop and a banner says why. |
| heldReason | string | "main is frozen for the 4.2 release" | Why the train is held. |
| merged | number | 0 | Changes merged so far today, for the header. |
| status | "running" | "loading" | "empty" | "error" | "running" | Whether the train's data has arrived; an empty train draws an empty depot. |
| onReload | () => void | — | Try again was pressed after the train failed to load. |
| title | string | "Merge train" | The heading and the listbox's name. |
| subtitle | string | "waylight/app · main" | Under the heading. |
| carStyle | "card" | "pill" | "boxcar" | "card" | A card with its checks, a compact pill, or a boxcar with a roof band and wheels. |
| trackStyle | "rails" | "transit" | "ruled" | "rails" | Rails and sleepers, one transit line with station rings, or a dashed hairline. |
| accent | "cobalt" | "plum" | "mint" | "ink" | string | "cobalt" | Running cars, progress and the open car: a named pigment or any CSS colour. |
| disabled | boolean | false | Read only: cars can be walked and read but not opened, moved or removed. |
| className | string | — | Classes for the surface; it caps at 36rem tall and its body scrolls inside. |