Kanban Board React component
A drag-and-drop task board with a hand-rolled pointer-based drag engine, velocity tilt, edge autoscroll, ghost drop-position indicator, priority badges, avatar stacks, and light/dark theming.
About the Kanban Board component
Kanban Board is a drag-and-drop task board with columns and cards. You pick a card up with the mouse, a finger or a pen, and it lifts, follows the pointer and tilts with the speed of the drag, while a dashed outline in the column's color shows where it will land. Near the left or right edge the board scrolls on its own, and dropping the card moves it into that column and position.
Each card can show a title, a tag with its own color, a note, a priority (urgent, high, medium or low, each with its own color) and up to four avatars. Columns have a title and an accent color, and showCounts puts the number of cards next to each title. The layout follows the width of the board itself, not the window: under 810px the columns stack vertically, so it also works inside a narrow panel. It has a light and a dark color set and a built-in theme toggle.
When to use it
Use it for roadmaps, sprint boards, hiring pipelines, content calendars and order or support queues, where items move through a fixed set of stages.
For a list that people sort, filter and page through rather than move between stages, use Data Table.
Installation
Add the Kanban Board component to your project with the shadcn CLI. It lands in components/kanban-board.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add @reactframe/kanban-boardOr copy the source by hand and install its dependencies:
npm install clsx tailwind-mergeProps
<KanbanBoard /> accepts 17 props, all optional.
| Prop | Type | Default |
|---|---|---|
| columns | { id: string; title: string; accentColor: string }[] | — |
| cards | KanbanCard[] | — |
| onCardsChange Called after a drag moves a card, with every card in its new column and order. | (cards: KanbanCard[]) => void | — |
| boardTitle | string | "Product Roadmap" |
| boardSubtitle | string | "Drag cards across columns to update status" |
| backgroundColor | string | "#f4f3f1" |
| inkColor | string | "#0d0d0d" |
| mutedColor | string | "#8a8a86" |
| surfaceColor | string | "#ffffff" |
| darkBackgroundColor | string | "#0d0d0d" |
| darkInkColor | string | "#f4f3f1" |
| darkMutedColor | string | "#9a9a96" |
- columns{ id: string; title: string; accentColor: string }[]
- cardsKanbanCard[]
- onCardsChange
Called after a drag moves a card, with every card in its new column and order.
(cards: KanbanCard[]) => void - boardTitlestringDefault: "Product Roadmap"
- boardSubtitlestringDefault: "Drag cards across columns to update status"
- backgroundColorstringDefault: "#f4f3f1"
- inkColorstringDefault: "#0d0d0d"
- mutedColorstringDefault: "#8a8a86"
- surfaceColorstringDefault: "#ffffff"
- darkBackgroundColorstringDefault: "#0d0d0d"
- darkInkColorstringDefault: "#f4f3f1"
- darkMutedColorstringDefault: "#9a9a96"
Show all 17 propsShow fewer
| darkSurfaceColor | string | "#1c1c1a" |
| defaultTheme | "light" | "dark" | "dark" |
| showThemeToggle | boolean | true |
| showCounts | boolean | true |
| className | string | — |
- darkSurfaceColorstringDefault: "#1c1c1a"
- defaultTheme"light" | "dark"Default: "dark"
- showThemeTogglebooleanDefault: true
- showCountsbooleanDefault: true
- classNamestring
Kits
Sets of components designed to be used together on one site, Kanban Board included.
npm dependencies
Installed for you by the shadcn CLI.
Kanban Board FAQ
- How do I save the new order after a drag?
- onCardsChange fires after each drop with every card, each carrying its new columnId, in the new order. Save that array to your backend or state. It only fires for moves made by the user, not when you pass new cards.
- Why do I see the demo cards when I pass an empty list?
- An empty cards (or columns) array falls back to the built-in demo data. To show an empty board, pass your columns with at least one card, or edit the defaults in the file.
- Does it work on touch screens?
- Yes. Dragging uses pointer events and the cards set touch-action: none, so a finger drags the card instead of scrolling the page.
- Can cards be moved with the keyboard?
- No. Moving cards is pointer-only, so if keyboard users need to change a card's status, give them another way to do it, such as a status menu in your card's detail view.
- How do I change the colors?
- backgroundColor, inkColor, mutedColor and surfaceColor set the light theme, and the matching dark props (darkBackgroundColor and so on) set the dark one. defaultTheme picks the starting theme, and showThemeToggle={false} hides the toggle.