facett-kanban — design note
Status: builds (egui 0.33) + 3 unit tests green. Lives in ordning/crates/widgets/facett-kanban; destined for the facett repo (see README).
What it is
A Kanban board facet: cases as draggable cards in columns (one per workflow status), optionally grouped into swimlanes (by assignee/priority/kind), with WIP limits per column. Dragging a card to another column is how a user transitions a case's status.
API
let mut board = Board::new("Support", vec![
Column::new("triage", "Triage"),
Column::new("active", "In Progress").wip(3), // WIP limit
Column::new("done", "Done"),
]).with_swimlanes(vec!["maria".into(), "john".into()]); // optional
board.set_cards(cards); // Vec<Card{ id, title, column, swimlane, assignee, priority, tags }>
board.ui(ui); // paint one frame (egui)
for mv in board.take_moves() { // drain drag-moves → apply as transitions
// host validates + fires the workflow transition; if rejected, board.set_cards(fresh)
}
Design decisions
- Drag-to-transition, host-validated. The board doesn't apply the status change itself — a drag records a
Move { card, from, to }. The host drainstake_moves(), runs it through the workflow engine's conditions/validators ([../05-funnel-tracker.md...] / manual ch.05), and only then commits. An invalid drop is rejected by re-set_cards. This keeps the board a view; the engine owns the rules. (Matches the architecture: the board is a projection of the event log, not a source of truth.) - WIP limits are first-class (Kanban discipline): a column over its limit warns in the header.
state_jsonexposeswip_breachper column so the queue-health view + tests see it. - egui dnd helpers (
dnd_drag_source/dnd_drop_zone) carry aDragCard(id)payload between card (source) and column (drop zone) — robust, no manual rect-hit-testing. state_json= the headless surface. Columns (count, wip_limit, wip_breach, card ids), lanes, selection, pending moves. A test asserts the board's content with no display (the facett discipline).- Swimlanes render as stacked rows of the same columns, filtered by lane key.
Move-to-facett notes
- Implements the facett
Facetshape already; under a futurefacettfeature, addimpl facett_core::Facet for Board { fn title/ui/state_json … fn caps() -> FacetCaps::SELECTABLE }. - Add
FieldValue-style theming viafacett_core::theme()instead of the hardcoded Color32s when it lands in facett (so it follows the active Theme). - Add an
egui_kittestheadless test clicking a card + assertingselectedinstate_json.
TODO when it matures
- Keyboard: arrow-move a selected card between columns (no mouse) — the Linear-grade bar.
- Column collapse; card count badges per swimlane; "add card" affordance per column.
- Virtualized card lists for very large columns.