nerdsnipe-inc/advancedkanban
A Kanban board component for SwiftUI on iOS, iPadOS, and macOS. You bring
Add a board in 3 steps
1. Conform your card type to KanbanCard — it only needs Identifiable and Equatable:
import AdvancedKanban
struct ExampleTask: KanbanCard {
let id: UUID
var title: String
}2. Conform your column type to KanbanColumn — it owns an ordered cards array (order is the board's display order, no separate sort index needed), an optional wipLimit, and an isCollapsed flag the board toggles on tap:
struct Stage: KanbanColumn {
let id: UUID
var name: String
var cards: [ExampleTask] = []
var wipLimit: Int? = nil
var isCollapsed: Bool = false
}3. Call KanbanBoard with a binding to your columns and view builders for card and column-header content:
import SwiftUI
import AdvancedKanban
struct ContentView: View {
@State private var columns: [Stage] = [
Stage(id: UUID(), name: "To Do", cards: [ExampleTask(id: UUID(), title: "Write README")]),
Stage(id: UUID(), name: "In Progress", wipLimit: 3),
Stage(id: UUID(), name: "Done"),
]
var body: some View {
KanbanBoard(
columns: $columns,
wipLimitBehavior: .preventDrop,
onMove: { move in
// move.cardID / .sourceColumnID / .destinationColumnID / .destinationIndex
// — persist however you like (SwiftData, a network call, analytics).
},
// Optional: gives VoiceOver real column names ("Move to In
// Progress") instead of describing the column by its raw id.
columnTitle: { $0.name },
cardContent: { task in
Text(task.title).padding(8)
},
columnHeader: { stage in
Text(stage.name).font(.headline)
}
)
}
}That's a complete, draggable, keyboard- and VoiceOver-accessible board. The onMove closure fires after the board has already mutated your columns binding, so it's purely a hook for persistence — you never diff arrays yourself.
Features
- Cross-column drag and drop — pointer-driven reorder within and across
columns, with edge autoscroll when dragging near the board's horizontal edges.
- Keyboard move-mode — Tab to focus a card, Space to enter move mode,
arrow keys to move within or across columns, Return to commit, Escape to cancel and restore the card's original position. No mouse required.
- Native pointer support on macOS — cards respond to hover with a
theme-agnostic highlight (visible in light and dark themes alike) and a grab/grabbing cursor (macOS 15+, gracefully absent on 14), and the drag gesture's activation threshold is tuned per platform — tight for a precise pointer (mouse/trackpad), the standard looser threshold for touch. The board is built to be embedded in real, native Mac apps, not just tolerated on one.
- VoiceOver parity — every drag interaction has an equivalent
accessibility action (Move Up / Move Down / Move to \<Column\>) exposed through the rotor, so VoiceOver users get the same reordering power as pointer and keyboard users.
- WIP limits — set
wipLimitper column and choose.warnOnly(the
column renders warning styling but the drop still succeeds) or .preventDrop (the drop is rejected and the card animates back) via wipLimitBehavior.
- Column collapse — columns collapse to a narrow title+count strip on
tap; state lives on your own isCollapsed property, so it's easy to persist.
- Theming —
KanbanThemecovers chrome-level tokens (backgrounds,
borders, corner radii, spacing, WIP warning color, drag ghost opacity, drop animation) and is applied with .kanbanTheme(_:). Card and column-header content is entirely yours via the cardContent and columnHeader view builders, so the theme never needs to know about your typography or layout.
- Optional SwiftData adapter —
AdvancedKanbanSwiftData(a separate
product) provides SwiftDataKanbanCard / SwiftDataKanbanColumn models and a KanbanStore that applies a KanbanMove to a ModelContext in one call. Not linked into the base AdvancedKanban library, so you're never forced into SwiftData if you don't want it.
Theming example
// The `KanbanBoard(...)` call is abbreviated here — see the full,
// copy-pasteable version in "Add a board in 3 steps" above. Only the
// `.kanbanTheme(_:)` modifier is the point of this snippet.
KanbanBoard(
columns: $columns,
cardContent: { task in Text(task.title).padding(8) },
columnHeader: { stage in Text(stage.name).font(.headline) }
)
.kanbanTheme(
KanbanTheme(
columnBackground: .gray.opacity(0.08),
cardBackground: .white,
cardBorder: .gray.opacity(0.2),
cardCornerRadius: 12,
cardSpacing: 8,
columnWidth: 280,
columnCornerRadius: 16,
wipLimitWarningColor: .orange,
dragGhostOpacity: 0.85,
dropAnimation: .spring(response: 0.35, dampingFraction: 0.8)
)
)KanbanTheme.default is used automatically if you don't apply one.
Example app
A runnable example lives in Example/. It demonstrates cross-column drag with a WIP limit, custom card content, theme switching, column collapse, keyboard reorder, and VoiceOver reorder — open Example/AdvancedKanbanExample.xcodeproj in Xcode and run it on macOS or an iOS/iPadOS simulator. Every view in the example also ships a #Preview, so you can inspect each theme/state combination directly in Xcode's canvas without running the app.
Two Xcode schemes are checked into the project — AdvancedKanbanExample (macOS) and AdvancedKanbanExample (iOS) — so opening the project gives a predictable, resizable native window on whichever platform you pick, rather than leaving Xcode to auto-select one.
Design spec
The full design rationale — protocol boundaries, drag-gesture state machine, keyboard/VoiceOver parity model, WIP limit semantics, and theming surface — is documented in docs/superpowers/specs/2026-08-19-advanced-kanban-design.md.
Installation
Swift Package Manager, via Xcode (File > Add Package Dependencies) or Package.swift:
dependencies: [
.package(url: "https://github.com/NerdSnipe-Inc/AdvancedKanban.git", from: "1.0.0")
]Then add the product(s) you need to your target:
.target(
name: "YourApp",
dependencies: [
.product(name: "AdvancedKanban", package: "AdvancedKanban"),
// Optional, only if you want the SwiftData persistence adapter:
.product(name: "AdvancedKanbanSwiftData", package: "AdvancedKanban"),
]
)Requires iOS 17+ / macOS 14+ and Swift 5.9+.
Also from NerdSnipe Inc
AdvancedKanban covers one component. If you're building the rest of the app around it, DesignFoundation Pro is a library of 47 production-ready SwiftUI screens and 29 SwiftUI UI blocks — AI Chat, CRM, Analytics, E-commerce, Social, Project Management, Onboarding, and more — built on the free, MIT-licensed DesignFoundation theming engine. Same theme token, every screen restyles.
License
AdvancedKanban is available under the MIT license. See LICENSE for the full text.
Package Metadata
Repository: nerdsnipe-inc/advancedkanban
Default branch: master
README: README.md