Kanban Card Movement
motiq/kanban-card-movementFreeComponent
An application-controlled Kanban interaction layer: pointer + touch + keyboard/menu card movement, drop validation, optimistic move with failure rollback, drop indicators, and empty columns. Dragging is never required. Clean-room (no external drag library); transform-based movement that doesn't re-render every card.
Live preview
live · rendered by the registry
Rendered by motiq on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.motiq.dev/r/kanban-card-movement.jsonSource
1"use client";23/* --------------------------------------------------------------------------4 * KanbanCardMovement — a presentation-only *card movement interaction layer*5 * for a board. It is NOT a project-management app: the host application owns6 * the columns, the cards, WIP limits, validation, and persistence. This7 * component renders that data and owns only the *movement UX* — pointer drag,8 * touch drag, keyboard pick-up-and-move, a non-drag "Move" menu, drop9 * validation, drop indicators, and optimistic movement with failure rollback.10 *11 * Movement is implemented CLEAN-ROOM on native Pointer events + CSS transforms12 * (Motion for React is used only for the layout/FLIP reflow when cards settle13 * into a new slot). There is deliberately **no** third-party drag-and-drop14 * dependency (no dnd-kit / react-dnd / sortable) so the component stays small15 * and isolated.16 *17 * Accessibility (never drag-only):18 * - Every card is a keyboard "pick up → arrow → drop" target (Space/Enter to19 * grab, arrows to move between columns + positions, Enter to drop, Escape to20 * cancel and return to origin).21 * - Every card also exposes an always-available **Move** menu — a full non-drag22 * path to move between columns with a mouse, keyboard, or switch device.23 * - Origin + destination are announced in a polite live region; focus returns24 * to the moved card after any move (drag, keyboard, menu, or rollback).25 * - Columns/drop targets are labelled; WIP-limit state is conveyed with text26 * (e.g. "Full"), never colour alone; reduced motion drops all transforms.27 *28 * Performance:29 * - During a pointer drag only the dragged card is repositioned, via a CSS30 * transform written straight to its ref inside requestAnimationFrame — there31 * is **no** React state update per `pointermove`. The only state that changes32 * mid-drag is the drop-slot index, and cards are `React.memo`'d so the rest33 * of the board does not re-render as the indicator moves.34 * - For very large boards, virtualize each column's card list (e.g.35 * `@tanstack/react-virtual`) and feed only the visible cards in as `cards`;36 * the movement math here is O(cards) per commit, not per frame, so it stays37 * cheap. Keep column card counts bounded or windowed for 60fps drag.38 *39 * Clean-room original.40 * ----------------------------------------------------------------------- */4142import * as React from "react";43import { motion } from "motion/react";4445// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from motiq
All 100 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Activity Streamactivity-stream | motiq | Components | Free | 1 dep | |
| Adaptive Safe-Zone Gridadaptive-safe-zone-grid | motiq | Components | Free | no deps | |
| Agent Run Timelineagent-run-timeline | motiq | Components | Free | 1 dep | |
| AI Response Streamai-response-stream | motiq | Components | Free | 1 dep | |
| Animated Accordionanimated-accordion | motiq | Components | Free | 2 deps | |
| Animated Buttonanimated-button | motiq | Components | Free | 1 dep | |
| Animated Dialoganimated-dialog | motiq | Components | Free | 2 deps | |
| Animated Gridanimated-grid | motiq | Components | Free | 2 deps |
