← All examples

Kanban board

A three-column board. Each column is its own Sortable instance, all sharing the board group so cards can move anywhere.

To do 3

  • Design onboarding flow
    design · 2d
  • Audit accessibility
    a11y · 1d
  • Write release notes
    docs · 30m

In progress 2

  • Implement search filter
    eng · 3d
  • Refactor auth module
    eng · 5d

Done 2

  • Migrate to v2
    eng · done
  • Update docs
    docs · done

How it was wired

import { Sortable } from '../src/index.ts'

const columns = ['col-todo', 'col-progress', 'col-done']

// Every column shares the same group ('board'), so cards can move
// freely between any two of them. `draggable: '.card-item'` scopes
// the drag handle to the visible card class (overriding the default
// '.sortable-item').
columns.forEach((id) => {
  new Sortable(document.getElementById(id), {
    group: 'board',
    animation: 150,
    draggable: '.card-item',
    ghostClass: 'sortable-ghost',
    // Both source and target columns need to refresh their counts
    // on cross-column moves, so subscribe to add/remove too.
    onSort: refreshCounts,
    onAdd: refreshCounts,
    onRemove: refreshCounts,
  })
})

function refreshCounts() {
  for (const col of columns) {
    const list = document.getElementById(col)
    const count = list.querySelectorAll('.card-item').length
    const slot = document.querySelector(
      `[data-count="${col.replace('col-', '')}"]`
    )
    if (slot) slot.textContent = String(count)
  }
}