Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Columnar drag-and-drop board with user-defined columns, count badges, and optional WIP limits.
A web component that renders a columnar drag-and-drop board with user-defined columns. Each column wraps a <drag-surface> for native drag-and-drop and keyboard-accessible reordering and transfer. Supports any draggable content — user-story cards, plain articles, or custom elements. Includes auto-updating count badges, optional WIP (work-in-progress) limits with visual warnings, and optional column color tinting.
<kanban-board> <section data-column="backlog" data-column-label="Backlog"> <user-story draggable="true" data-id="PROJ-201" story-id="PROJ-201" priority="high" status="to-do" points="5" detail="minimal"> <span slot="persona">Sarah Chen</span> <span slot="action">view all project timelines in one dashboard</span> </user-story> </section> <section data-column="in-progress" data-column-label="In Progress"> <user-story draggable="true" data-id="PROJ-198" story-id="PROJ-198" priority="high" status="in-progress" points="5" detail="minimal"> <span slot="persona">Jordan Park</span> <span slot="action">filter reports by date range and team</span> </user-story> </section> <section data-column="review" data-column-label="Review"> </section> <section data-column="done" data-column-label="Done" data-column-color="success"> </section></kanban-board>
| Attribute | Type | Description |
|---|---|---|
src | string | URL to JSON data for columns and items |
title | string | Optional heading displayed above the board |
compact | boolean | Reduced spacing variant for dashboard-style layouts |
Set these on <section> children to define columns:
| Attribute | On | Type | Description |
|---|---|---|---|
data-column | <section> | string | Column identifier (e.g. "backlog", "doing", "done") |
data-column-label | <section> | string | Display label for the column header. Falls back to title-cased data-column |
data-wip | <section> | number | Optional WIP limit. Visual warning when exceeded |
data-column-color | <section> | string | Color token for column tint: success, warning, error, info |
Set these on draggable children within sections:
| Attribute | Type | Description |
|---|---|---|
draggable="true" | boolean | Required for drag capability (auto-added if missing) |
data-id | string | Stable identifier for the item (auto-generated if missing) |
Add data-wip to any column section to set a work-in-progress limit. When the number of items in a column exceeds the limit, the component adds a data-wip-exceeded attribute to the column and fires a kanban-board:wip-exceeded event. Items are not blocked from entering — this is a visual warning only.
<kanban-board> <section data-column="backlog" data-column-label="Backlog"> <article draggable="true" data-id="task-1">Task A</article> <article draggable="true" data-id="task-2">Task B</article> </section> <section data-column="doing" data-column-label="In Progress" data-wip="2"> <article draggable="true" data-id="task-3">Task C</article> <article draggable="true" data-id="task-4">Task D</article> </section> <section data-column="done" data-column-label="Done"> </section></kanban-board>
The board is not limited to sprint planning. Any draggable content works — blog posts through a publishing pipeline, support tickets, hiring candidates, or content workflows.
<kanban-board> <section data-column="ideas" data-column-label="Ideas" data-column-color="info"> <article draggable="true" data-id="post-1"> <strong>CSS Container Queries Deep Dive</strong> <small>Tutorial</small> </article> </section> <section data-column="drafting" data-column-label="Drafting" data-wip="2"> </section> <section data-column="published" data-column-label="Published" data-column-color="success"> </section></kanban-board>
| Event | Detail | Description |
|---|---|---|
kanban-board:transfer | { itemId, fromColumn, toColumn, newIndex, item } | Item moved between columns |
kanban-board:reorder | { itemId, column, oldIndex, newIndex } | Item reordered within a column |
kanban-board:ready | { columnCount, itemCount } | Fired after component initializes |
kanban-board:wip-exceeded | { column, limit, count } | Fired when a column exceeds its WIP limit |
Set the src attribute to load board data from a JSON URL. Items with storyId fields are rendered as <user-story> elements with persona and action content in slots. All other items are rendered as <article> elements.
{ "columns": [ { "id": "backlog", "label": "Backlog", "wip": null, "color": null, "items": [ { "id": "task-1", "text": "Design review" }, { "id": "PROJ-201", "storyId": "PROJ-201", "persona": "Sarah Chen", "action": "view timelines", "priority": "high", "detail": "minimal" } ] } ]}
All keyboard support is provided by the underlying <drag-surface> component:
role="region" with aria-label="Kanban board"aria-label matching the column label<output> elements for live value updatesprefers-reduced-motion: reduce<drag-surface> — the underlying drag-and-drop engine<story-map> — horizontal story map with activity columns<impact-effort> — 2×2 prioritization matrix<user-story> — Agile story cards to use as board items