Skip to content

Swimlanes, WIP, And Rules

Use swimlanes when each workflow column must be split by team, class of service, release, product area, or another card field.

Swimlane labels render in a dedicated row-header column by default. Use swimlaneLayout: 'top' to render a compact header across the workflow columns before each lane instead. Both layouts keep counts, custom header content, and per-lane collapse controls.

grid.kanban = {
columns,
swimlaneField: 'team',
swimlaneLayout: 'top', // use 'column' for the dedicated label column
swimlanes: [
{ id: 'product', title: 'Product team', collapsible: true },
{ id: 'platform', title: 'Platform team', collapsible: true },
],
};

column is the backward-compatible default. swimlaneColumn width and collapse settings apply only to that dedicated-column layout.

Setting only swimlaneField derives lanes in first-appearance order. Provide definitions when labels, order, heights, collapse controls, styles, or lane-specific WIP limits matter.

grid.kanban = {
columns,
swimlaneField: 'team',
swimlanes: [
{ id: 'web', title: 'Web team', wipLimits: { active: 2 } },
{ id: 'api', title: 'API team', collapsed: false },
],
};

Swimlane order is configuration-owned and cannot be dragged in v1.

For a board that does not use swimlanes, disable the row-header presentation directly in Kanban configuration:

grid.kanban = {
columns,
swimlaneColumn: false,
};

Cards still use the internal implicit lane for ordering and virtualization, but no swimlane label or lane-collapse control is rendered.

The swimlane row-header column can collapse independently from the lanes. In its compact state it shrinks to a narrow rail and renders lane titles as vertical badges; cards and lane heights are unchanged.

grid.kanban = {
columns,
swimlaneField: 'team',
swimlaneColumn: {
title: 'Teams',
width: 176,
collapsedWidth: 52,
collapsible: true,
collapsed: false,
},
};

Use getSwimlaneColumnCollapsed() and setSwimlaneColumnCollapsed(...) on the plugin instance when an application toolbar also needs to control the state. This is separate from each swimlane definition’s collapsed state, which reduces that lane’s projected row height.

Set a column wipLimit, or a lane wipLimits entry for a more specific bucket limit. wipBehavior defaults to warn:

  • warn permits the move and renders/announces the over-limit state.
  • block rejects the entire proposed move.

Multi-card moves validate the final batch count, not each card independently. A failed card or capacity check cancels the full move.

Use allowedFrom for simple workflow transitions and rules for application policy:

rules: {
canDrag: (card) => card.locked ? 'Locked by another user' : true,
canSelect: (card) => !card.archived,
canEdit: (card) => card.permissions.includes('edit'),
canDrop: ({ cards, targetColumn }) =>
cards.some((card) => card.requiresApproval) && targetColumn.prop === 'done'
? 'Approval is required'
: true,
}

Return false or a localized reason string to reject an action.

cardRules is an ordered declarative layer for badges, classes, styles, and permissions. Matching classes and badges accumulate, later styles override earlier properties, and any explicit permission denial wins.

cardRules: [
{
id: 'urgent',
when: ({ card }) => card.priority === 'urgent',
result: {
className: 'card--urgent',
badges: [{ label: 'Urgent' }],
style: { '--kanban-card-accent': '#dc2626' },
},
},
]