KQ-1724 · STACK/CARRY

Stack Carry

A kanban board where a selection moves as one stack. Dragging any selected card gathers the others under the pointer into a fan whose spread is fanAngle: the grabbed card follows 1:1 and each card behind it follows on its own spring, softer the deeper it sits, so a fast throw strings the deck out and a pause gathers it, while a count badge lands on springs.recoil. Dropping deals the cards into the column in their original board order on springs.glide, cascade() apart, as their dashed home slots fold shut and the cards around them FLIP to make room; refused cards fly home, shake once and say why. Shift-click selects a run, Cmd or Ctrl-click or the check tab toggles, X toggles the focused card, M opens a move menu that deals the same way, Escape clears, and a long press starts selecting on touch.

KQ-1724 · STACK/CARRY

Coldbrook Support

Tuesday queue · 11 tickets

selected2 selected

New

52 sel
  • CB-104840m

    Card declined at checkout

    Harbour Deli

  • CB-10471h

    Export stuck at 90%

    Tidewater Co.

  • CB-10462h

    Change billing email

    Moss & Rye

  • CB-10453h

    Duplicate invoice in March

    Pellar Studio

  • CB-10445h

    Sign-in loops back to start

    Northgate Rowing

Assigned

2
  • CB-10431d

    Add a second admin

    Fenn Bakery

  • CB-10401d

    Cancel annual plan

    Quayside Books

Waiting

2
  • CB-10422d

    Refund for a double charge

    Harbour Deli

  • CB-10412d

    Receipt missing VAT number

    Larch Joinery

Solved

2
  • CB-10393d

    Webhook retries doubled

    Tidewater Co.

  • CB-10384d

    Password reset email late

    Fenn Bakery

Arrows move between tickets, Shift with Up or Down extends the selection, X or Space selects, M moves the selection to a column, Escape clears it. Drag a selected ticket to carry them all.

2 selected · New

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/stack-carry

Props

columns
StackColumn[]
default defaultStackColumns
The columns, left to right: { id, title }.
cards / defaultCards
StackCard[]
default — / defaultStackCards
The cards, controlled or initial, in column order: { id, title, column, customer?, priority?, openedAt? }.
onCardsChange
(cards: StackCard[]) => void
default —
Fires with the whole board once a move has landed.
selected / defaultSelected
string[]
default — / []
The selected card ids, controlled or initial.
onSelect
(ids: string[]) => void
default —
Fires from the click, key or long press that changed the selection, with the ids in board order; also after a move, with the refused cards that stay selected.
onMoveMany
(ids: string[], toColumn: string, index: number) => StackMoveResult | void | Promise<StackMoveResult | void>
default —
Moves the cards. Answer now or later with { failed: [{ id, reason }] } for any that could not move; the rest land in board order at index among the column's other cards. While a promise is pending the stack waits and its badge spins.
fanAngle
number
default 7
How far the carried stack fans, in degrees per card; 0 is a neat pile.
maxFan
number
default 5
Cards drawn in the carried stack; the badge counts the rest.
cardStyle
"raised" | "flat" | "outline"
default "raised"
Card surface: raised with a shadow, a flat tint, or an outline on the board colour.
accent
string
default "var(--accent-bright)"
Selection border and check tab, the stack's badge, the drop wash and the Move button. Any CSS colour.
longPressMs
number
default 450
How long a finger holds a card before selecting starts, in ms.
now
number
default Date.UTC(2026, 9, 13, 11)
The moment ticket ages are read against, in ms. Never the wall clock.
title
string
default "Coldbrook Support"
The board's heading.
subtitle
string
default "Tuesday queue"
One line under the heading, followed by the ticket count.
status
"ready" | "loading" | "error"
default "ready"
Whether the board has loaded: loading shows skeleton columns, error a message with Try again.
onReload
() => void
default —
Try again was pressed after the board failed to load.
disabled
boolean
default false
Read-only: cards can be selected but nothing moves.
className
string
default —
Classes for the outer container.