- Prop
columns- Type
CoreKanbanColumn[]- Default
- —
- Requirement
- required
Docs Components Advanced
Kanban
React example follows below.
Vue example follows below.
Angular example follows below.
Svelte example follows below.
Solid example follows below.
- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
/** * Kanban's pinned demo state (CSP-D3). * * Four columns so the board fills its `md:grid-cols-4` root, and the card * distribution is deliberately uneven — two in the first column, one in each * middle column, one at the end — so the demo renders a card *mid-column* * rather than only at the ends, and every column header shows a different * live count. Both `priority` tags and both assignee-chip states (with and * without an explicit chip colour) appear at least once. * * `rail` / `assigneeColor` carry raw token strings under names the fixture * proof allows; a bare `color` key would be rejected. */const kanbanFixture = { id: "kanban", columns: [ { id: "backlog", name: "Backlog", rail: "var(--text-muted)" }, { id: "progress", name: "In progress", rail: "var(--accent)" }, { id: "review", name: "In review", rail: "var(--vs-info)" }, { id: "done", name: "Done", rail: "var(--vs-success)" }, ], cards: [ { id: "card-rotate-keys", columnId: "backlog", title: "Rotate signing keys", priority: "high", assignee: "AM", assigneeColor: "var(--accent)", }, { id: "card-retry-budget", columnId: "backlog", title: "Per-tenant retry budget", priority: "low", assignee: "RS", }, { id: "card-idempotency", columnId: "progress", title: "Idempotency keys", priority: "high", assignee: "JL", assigneeColor: "var(--vs-info)", }, { id: "card-webhook-replay", columnId: "review", title: "Webhook replay window", priority: "med", assignee: "PK", assigneeColor: "var(--vs-warning)", }, { id: "card-ledger-cutover", columnId: "done", title: "Ledger cutover runbook", priority: "med", assignee: "TD", assigneeColor: "var(--vs-success)", }, ],} satisfies { id: string; columns: { id: string; name: string; rail: string }[]; cards: { id: string; columnId: string; title: string; priority: "low" | "med" | "high"; assignee: string; assigneeColor?: string; }[];}; import { Kanban } from "@grassroot/ui-react/advanced"; export default function KanbanDemo() { return ( <div> <Kanban columns={kanbanFixture.columns} defaultCards={kanbanFixture.cards} /> </div> );}- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
<script setup lang="ts">/** * Kanban's pinned demo state (CSP-D3). * * Four columns so the board fills its `md:grid-cols-4` root, and the card * distribution is deliberately uneven — two in the first column, one in each * middle column, one at the end — so the demo renders a card *mid-column* * rather than only at the ends, and every column header shows a different * live count. Both `priority` tags and both assignee-chip states (with and * without an explicit chip colour) appear at least once. * * `rail` / `assigneeColor` carry raw token strings under names the fixture * proof allows; a bare `color` key would be rejected. */const kanbanFixture = { id: "kanban", columns: [ { id: "backlog", name: "Backlog", rail: "var(--text-muted)" }, { id: "progress", name: "In progress", rail: "var(--accent)" }, { id: "review", name: "In review", rail: "var(--vs-info)" }, { id: "done", name: "Done", rail: "var(--vs-success)" }, ], cards: [ { id: "card-rotate-keys", columnId: "backlog", title: "Rotate signing keys", priority: "high", assignee: "AM", assigneeColor: "var(--accent)", }, { id: "card-retry-budget", columnId: "backlog", title: "Per-tenant retry budget", priority: "low", assignee: "RS", }, { id: "card-idempotency", columnId: "progress", title: "Idempotency keys", priority: "high", assignee: "JL", assigneeColor: "var(--vs-info)", }, { id: "card-webhook-replay", columnId: "review", title: "Webhook replay window", priority: "med", assignee: "PK", assigneeColor: "var(--vs-warning)", }, { id: "card-ledger-cutover", columnId: "done", title: "Ledger cutover runbook", priority: "med", assignee: "TD", assigneeColor: "var(--vs-success)", }, ],} satisfies { id: string; columns: { id: string; name: string; rail: string }[]; cards: { id: string; columnId: string; title: string; priority: "low" | "med" | "high"; assignee: string; assigneeColor?: string; }[];}; import { Kanban } from "@grassroot/ui-vue";</script> <template> <div> <Kanban :columns="kanbanFixture.columns" :default-cards="kanbanFixture.cards" /> </div></template>- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
import { Component } from "@angular/core";/** * Kanban's pinned demo state (CSP-D3). * * Four columns so the board fills its `md:grid-cols-4` root, and the card * distribution is deliberately uneven — two in the first column, one in each * middle column, one at the end — so the demo renders a card *mid-column* * rather than only at the ends, and every column header shows a different * live count. Both `priority` tags and both assignee-chip states (with and * without an explicit chip colour) appear at least once. * * `rail` / `assigneeColor` carry raw token strings under names the fixture * proof allows; a bare `color` key would be rejected. */const kanbanFixture = { id: "kanban", columns: [ { id: "backlog", name: "Backlog", rail: "var(--text-muted)" }, { id: "progress", name: "In progress", rail: "var(--accent)" }, { id: "review", name: "In review", rail: "var(--vs-info)" }, { id: "done", name: "Done", rail: "var(--vs-success)" }, ], cards: [ { id: "card-rotate-keys", columnId: "backlog", title: "Rotate signing keys", priority: "high", assignee: "AM", assigneeColor: "var(--accent)", }, { id: "card-retry-budget", columnId: "backlog", title: "Per-tenant retry budget", priority: "low", assignee: "RS", }, { id: "card-idempotency", columnId: "progress", title: "Idempotency keys", priority: "high", assignee: "JL", assigneeColor: "var(--vs-info)", }, { id: "card-webhook-replay", columnId: "review", title: "Webhook replay window", priority: "med", assignee: "PK", assigneeColor: "var(--vs-warning)", }, { id: "card-ledger-cutover", columnId: "done", title: "Ledger cutover runbook", priority: "med", assignee: "TD", assigneeColor: "var(--vs-success)", }, ],} satisfies { id: string; columns: { id: string; name: string; rail: string }[]; cards: { id: string; columnId: string; title: string; priority: "low" | "med" | "high"; assignee: string; assigneeColor?: string; }[];}; import { GrassrootKanban } from "@grassroot/ui-angular"; // Every input is a `[property]` binding, never a static attribute — Angular// leaves static template attributes on the host element in the rendered DOM,// where the other four frameworks have nothing.@Component({ selector: "app-kanban-demo", standalone: true, imports: [GrassrootKanban], template: ` <div> <grassroot-kanban [columns]="columns" [defaultCards]="cards" /> </div> `,})export class KanbanDemoComponent { protected readonly columns = kanbanFixture.columns; protected readonly cards = kanbanFixture.cards;} export default KanbanDemoComponent;- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
<script lang="ts"> /** * Kanban's pinned demo state (CSP-D3). * * Four columns so the board fills its `md:grid-cols-4` root, and the card * distribution is deliberately uneven — two in the first column, one in each * middle column, one at the end — so the demo renders a card *mid-column* * rather than only at the ends, and every column header shows a different * live count. Both `priority` tags and both assignee-chip states (with and * without an explicit chip colour) appear at least once. * * `rail` / `assigneeColor` carry raw token strings under names the fixture * proof allows; a bare `color` key would be rejected. */ const kanbanFixture = { id: "kanban", columns: [ { id: "backlog", name: "Backlog", rail: "var(--text-muted)" }, { id: "progress", name: "In progress", rail: "var(--accent)" }, { id: "review", name: "In review", rail: "var(--vs-info)" }, { id: "done", name: "Done", rail: "var(--vs-success)" }, ], cards: [ { id: "card-rotate-keys", columnId: "backlog", title: "Rotate signing keys", priority: "high", assignee: "AM", assigneeColor: "var(--accent)", }, { id: "card-retry-budget", columnId: "backlog", title: "Per-tenant retry budget", priority: "low", assignee: "RS", }, { id: "card-idempotency", columnId: "progress", title: "Idempotency keys", priority: "high", assignee: "JL", assigneeColor: "var(--vs-info)", }, { id: "card-webhook-replay", columnId: "review", title: "Webhook replay window", priority: "med", assignee: "PK", assigneeColor: "var(--vs-warning)", }, { id: "card-ledger-cutover", columnId: "done", title: "Ledger cutover runbook", priority: "med", assignee: "TD", assigneeColor: "var(--vs-success)", }, ], } satisfies { id: string; columns: { id: string; name: string; rail: string }[]; cards: { id: string; columnId: string; title: string; priority: "low" | "med" | "high"; assignee: string; assigneeColor?: string; }[]; }; import { Kanban } from "@grassroot/ui-svelte";</script> <div> <Kanban columns={kanbanFixture.columns} defaultCards={kanbanFixture.cards} /></div>- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
/** @jsxImportSource solid-js *//** * Kanban's pinned demo state (CSP-D3). * * Four columns so the board fills its `md:grid-cols-4` root, and the card * distribution is deliberately uneven — two in the first column, one in each * middle column, one at the end — so the demo renders a card *mid-column* * rather than only at the ends, and every column header shows a different * live count. Both `priority` tags and both assignee-chip states (with and * without an explicit chip colour) appear at least once. * * `rail` / `assigneeColor` carry raw token strings under names the fixture * proof allows; a bare `color` key would be rejected. */const kanbanFixture = { id: "kanban", columns: [ { id: "backlog", name: "Backlog", rail: "var(--text-muted)" }, { id: "progress", name: "In progress", rail: "var(--accent)" }, { id: "review", name: "In review", rail: "var(--vs-info)" }, { id: "done", name: "Done", rail: "var(--vs-success)" }, ], cards: [ { id: "card-rotate-keys", columnId: "backlog", title: "Rotate signing keys", priority: "high", assignee: "AM", assigneeColor: "var(--accent)", }, { id: "card-retry-budget", columnId: "backlog", title: "Per-tenant retry budget", priority: "low", assignee: "RS", }, { id: "card-idempotency", columnId: "progress", title: "Idempotency keys", priority: "high", assignee: "JL", assigneeColor: "var(--vs-info)", }, { id: "card-webhook-replay", columnId: "review", title: "Webhook replay window", priority: "med", assignee: "PK", assigneeColor: "var(--vs-warning)", }, { id: "card-ledger-cutover", columnId: "done", title: "Ledger cutover runbook", priority: "med", assignee: "TD", assigneeColor: "var(--vs-success)", }, ],} satisfies { id: string; columns: { id: string; name: string; rail: string }[]; cards: { id: string; columnId: string; title: string; priority: "low" | "med" | "high"; assignee: string; assigneeColor?: string; }[];}; import { Kanban } from "@grassroot/ui-solid"; export default function KanbanDemo() { return ( <div> <Kanban columns={kanbanFixture.columns} defaultCards={kanbanFixture.cards} /> </div> );}Installation
API Reference
Import
import { Kanban } from "@grassroot/ui-react/advanced";
Props
Prop
Type
Default
Requirement
columnsCoreKanbanColumn[]—
required
cardsCoreKanbanCard[] | undefined—
optional
defaultCardsCoreKanbanCard[] | undefined—
optional
onMove((cardId: string, toColumnId: string) => void) | undefined—
optional
disableDragboolean | undefined—
optional
- Prop
cards- Type
CoreKanbanCard[] | undefined- Default
- —
- Requirement
- optional
- Prop
defaultCards- Type
CoreKanbanCard[] | undefined- Default
- —
- Requirement
- optional
- Prop
onMove- Type
((cardId: string, toColumnId: string) => void) | undefined- Default
- —
- Requirement
- optional
- Prop
disableDrag- Type
boolean | undefined- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
onMove | ((cardId: string, toColumnId: string) => void) | undefined |
Native attributes
Standard DOM and ARIA attributes not listed above spread onto the root element.
Import
import { Kanban } from "@grassroot/ui-vue";
Props
Prop
Type
Default
Requirement
columnsKanbanColumn[]—
required
cardsKanbanCard[] | undefined—
optional
defaultCardsKanbanCard[] | undefined() => []optional
disableDragboolean | undefinedfalseoptional
- Prop
columns- Type
KanbanColumn[]- Default
- —
- Requirement
- required
- Prop
cards- Type
KanbanCard[] | undefined- Default
- —
- Requirement
- optional
- Prop
defaultCards- Type
KanbanCard[] | undefined- Default
() => []- Requirement
- optional
- Prop
disableDrag- Type
boolean | undefined- Default
false- Requirement
- optional
Events
| Event | Payload |
|---|---|
move | [cardId: string, toColumnId: string] |
Import
import { Component } from "@angular/core";
import { GrassrootKanban } from "@grassroot/ui-angular";
Props
Prop
Type
Default
Requirement
columnsKanbanColumn[]—
required
cardsKanbanCard[]—
optional
defaultCardsKanbanCard[][]optional
disableDragbooleanfalseoptional
- Prop
columns- Type
KanbanColumn[]- Default
- —
- Requirement
- required
- Prop
cards- Type
KanbanCard[]- Default
- —
- Requirement
- optional
- Prop
defaultCards- Type
KanbanCard[]- Default
[]- Requirement
- optional
- Prop
disableDrag- Type
boolean- Default
false- Requirement
- optional
Events
| Event | Payload |
|---|---|
move | { cardId: string; toColumnId: string } |
Import
import { Kanban } from "@grassroot/ui-svelte";
Props
Prop
Type
Default
Requirement
columnsKanbanColumn[]—
required
cardsKanbanCard[]—
optional
defaultCardsKanbanCard[]—
optional
onMove(cardId: string, toColumnId: string) => void—
optional
disableDragbooleanfalseoptional
classNamestring—
optional
- Prop
columns- Type
KanbanColumn[]- Default
- —
- Requirement
- required
- Prop
cards- Type
KanbanCard[]- Default
- —
- Requirement
- optional
- Prop
defaultCards- Type
KanbanCard[]- Default
- —
- Requirement
- optional
- Prop
onMove- Type
(cardId: string, toColumnId: string) => void- Default
- —
- Requirement
- optional
- Prop
disableDrag- Type
boolean- Default
false- Requirement
- optional
- Prop
className- Type
string- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
onMove | (cardId: string, toColumnId: string) => void |
Import
import { Kanban } from "@grassroot/ui-solid";
Props
Prop
Type
Default
Requirement
columnsKanbanColumn[]—
required
cardsKanbanCard[]—
optional
defaultCardsKanbanCard[]—
optional
onMove(cardId: string, toColumnId: string) => void—
optional
disableDragboolean—
optional
classNamestring—
optional
- Prop
columns- Type
KanbanColumn[]- Default
- —
- Requirement
- required
- Prop
cards- Type
KanbanCard[]- Default
- —
- Requirement
- optional
- Prop
defaultCards- Type
KanbanCard[]- Default
- —
- Requirement
- optional
- Prop
onMove- Type
(cardId: string, toColumnId: string) => void- Default
- —
- Requirement
- optional
- Prop
disableDrag- Type
boolean- Default
- —
- Requirement
- optional
- Prop
className- Type
string- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
onMove | (cardId: string, toColumnId: string) => void |