Draggable
Drag-and-drop board patterns for prioritization, workflows, and quick task grooming
Draggable surfaces work best when movement is obvious, drop zones are forgiving, and lock states are explicit. This page documents board-style drag behavior with handles, hover states, reorder rules, and a live preview you can shuffle and test in place.
1. Variant Matrix
Common draggable board configurations for admin workflows
2. Board Playground
Tune the board rules on the left panel, then drag cards across the live board on the right
Three-column drag board with handles and one locked card.
3. Movement Rules
Make movement predictable before making it fast
- Highlight only valid targets to reduce hesitation.
- Keep column hit areas generous, especially on touch devices.
- Persist the reorder immediately after drop, not on later save.
- Moving across columns should communicate status change, not just order change.
- Locked or system-controlled cards need explicit affordance and explanation.
- Offer keyboard alternatives for reorder actions where possible.
4. State Modeling
Differentiate movable, active, and restricted cards at a glance
Use cursor, handle, and hover shadow together so the interaction is clear before the drag starts.
Use a dashed boundary plus lock chip. Avoid silent failure when users try to drag a restricted item.
5. Accessibility & Touch
Drag should degrade cleanly across keyboard, touch, and assistive tech
Expose alternate move actions such as "Move left" or "Move to done" in menus when raw drag is unavailable.
Give handles enough width for touch and avoid placing them too close to destructive controls.
6. Real-use Snippets
Copy-ready board markup and state utilities
<article class="drag-card" draggable="true">
<div class="drag-card__head">
<div class="drag-card__main">
<h4 class="drag-card__title">Refine onboarding flow</h4>
<p class="drag-card__text">Move between backlog and in-progress lanes.</p>
</div>
<span class="drag-handle"><i class="fa-solid fa-grip-lines"></i> Drag</span>
</div>
</article>
<div class="board-shell board-shell--3"> <section class="drag-column">...</section> <section class="drag-column">...</section> <section class="drag-column">...</section> </div>
.drag-card.is-dragging { opacity: .58; box-shadow: var(--shadow-pop); }
.drag-column.is-over { border-color: color-mix(in srgb, var(--brand) 58%, var(--border)); }
.drag-card.is-locked { cursor: not-allowed; border-style: dashed; }