KQ-1303 · SWIM/BOARD

Swim Board

A kanban board with swimlanes. A dragged card comes up into a carried copy 1:1 under the pointer, scaled on flick and leaning into its horizontal speed up to tilt degrees on a glide-tuned spring; the cell under it opens a gap of the card's exact height on glide while the cards below slide down, and on release it flies into the gap on snap with the release velocity and straightens as it lands. A move past a column's work-in-progress limit shakes its header on a five-beat tween and turns it warn (or is refused, the gap staying home), lanes group by priority or owner and fold on glide, and moving a card between lanes rewrites that field. Space picks a focused card up, arrows carry it a place or a column at a time, Enter drops and Escape puts it back, every step announced.

KQ-1303 · SWIM/BOARD

Sprint 14

12 cards · in progress 3/3

Space picks a card up. Arrow keys move it a place or a column, Enter drops it, Escape puts it back. Arrow keys alone move between cards.

Backlog

4

In progress

3/3

Review

2/2

Done

3

      sprint 14 · drag a card, or focus one and press space to pick it up

      Install

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

      $ pnpm dlx shadcn@latest add @kinetiq/swim-board

      Props

      cards / defaultCards
      SwimCard[]
      default defaultSwimCards
      Every card in board order — a cell lists its cards in the order they appear here. Each has a title, column, priority, owner, and optional tag and points. Controlled or uncontrolled.
      onCardsChange
      (cards: SwimCard[], move: SwimMove) => void
      default —
      Fires from the drop that moved a card, with every card and the move (from and to as column, lane and index, and whether it came from the pointer or the keyboard).
      columns
      SwimColumn[]
      default defaultSwimColumns
      The columns left to right, each with an optional work-in-progress limit.
      people
      SwimPerson[]
      default defaultSwimPeople
      Everyone a card can belong to; owner lanes follow this order.
      onMove
      (move: SwimMove) => void
      default —
      A card was dropped somewhere new.
      onCardOpen
      (id: string) => void
      default —
      A card was tapped, clicked, or had Enter pressed on it while not picked up.
      onLaneToggle
      (lane: string, collapsed: boolean) => void
      default —
      A lane was folded or unfolded, with its new state.
      tilt
      number
      default 6
      How far a carried card leans into its travel, in degrees: its angle is the pointer's horizontal speed, clamped to this. 0 keeps it level.
      limit
      "warn" | "block" | "off"
      default "warn"
      Work-in-progress limits: a move past one shakes the header and turns it warn, is refused with the card going home, or limits are hidden.
      lanes
      "priority" | "owner" | "none"
      default "priority"
      What the rows group by. Moving a card between lanes rewrites that field on the card.
      collapsedLanes / defaultCollapsedLanes
      string[]
      default []
      Folded lanes by id. Controlled (with onLaneToggle) or uncontrolled.
      title
      string
      default "Sprint 14"
      The board's heading.
      subtitle
      string
      default "Fernworks Field app"
      A quieter line beside the heading, from 480px.
      status
      "ready" | "loading" | "error"
      default "ready"
      Skeleton cards while loading; a message with Retry on error.
      onRetry
      () => void
      default —
      The error state's Retry button.
      label
      string
      default title
      The board's accessible name.
      sound
      boolean
      default false
      A click as a card comes up or a lane folds, a thock pitched by column as it lands — duller when a drop is refused.
      disabled
      boolean
      default false
      Cards can still be read and walked with the arrow keys, but not carried or opened.
      className
      string
      default —
      Classes for the root. It is 560px tall by default; the lanes scroll inside it.