Guide
Theming
A theme is a set of chrome tokens applied with one modifier. It never touches what's inside a card.
Where the boundary is
AdvancedKanban renders chrome — the card's background, border, corner radius, shadow; the column's background and corner radius; the WIP-warning color; the drag ghost's opacity and the drop animation. It does not render anything inside a card or a column header — that's your cardContent and columnHeader view builders, and it stays that way deliberately: a fixed card schema is the most common complaint in Kanban component libraries, and typography/layout choices belong to your app's design system, not the package's.
Because content is entirely yours, text color inside a card is your responsibility — not the theme's. If your card content uses .primary and your theme sets a fixed light cardBackground under a dark system appearance, you'll get white-on-white. Give your card content an explicit color that's paired with whatever background your theme actually renders, the same way you'd theme any other view.
Applying a theme
KanbanBoard(/* ... */) .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) ))
Read from @Environment(\.kanbanTheme) anywhere below the modifier if your own views want to match — it's a plain SwiftUI environment value, not something internal to the package.
KanbanTheme reference
| Field | Type | Default |
|---|---|---|
| columnBackground | Color | System secondary background |
| cardBackground | Color | System background |
| cardBorder | Color | .gray.opacity(0.25) |
| cardCornerRadius | CGFloat | 10 |
| cardSpacing | CGFloat | 8 |
| columnWidth | CGFloat | 280 |
| columnCornerRadius | CGFloat | 14 |
| wipLimitWarningColor | Color | .orange |
| dragGhostOpacity | Double | 0.85 |
| dropAnimation | Animation | .spring(response: 0.35, dampingFraction: 0.8) |
KanbanTheme.default is applied automatically if you never call .kanbanTheme(_:) — the values above are exactly what it uses.
Switching themes at runtime
Since .kanbanTheme(_:) is a plain modifier, driving it from @State just works — no special API:
@State private var highContrast = false KanbanBoard(/* ... */) .kanbanTheme(highContrast ? .highContrastTheme : .default)