Configuration
WIP Limits
Set a work-in-progress limit on a column to visually indicate when too many cards are assigned. The column header shows the current count vs. limit, and the header is highlighted when the limit is exceeded.
// Set a WIP limit
column.wipLimit = 3;
// Remove the limit
column.wipLimit = null;
// Check programmatically
const exceeded = board.data.isWipLimitExceeded(column.id);
const count = board.data.getCardCountInColumn(column.id);Terminal Columns
Mark a column as terminal to indicate it represents a final workflow state (e.g. Done, Closed). Cards in terminal columns are visually dimmed.
const done = new KanbanColumn(null);
done.title = 'Done';
done.isTerminal = true;Collapsed State
Columns and swimlanes can be collapsed to save space. Collapsed columns show only the card count. Collapsed swimlanes show only the header row.
// Collapse a column
column.collapsed = true;
// Collapse a swimlane
swimlane.collapsed = true;Read-only Mode
Disable all editing — drag-and-drop, card deletion, and other mutations are blocked.
board.canEdit = false;Custom Card Rendering
Override the default card appearance with a custom render function. The function receives the card and a container element — populate it with any HTML.
// The render function receives a CardRenderArgs object:
// { card, element, column, swimlane, color }
board.cardRendering = (args) => {
args.element.innerHTML = `
<div style="padding: 8px;">
<strong>${args.card.title}</strong>
<div style="font-size: 12px; color: #888;">
${args.card.priority !== 'none' ? args.card.priority.toUpperCase() : ''}
</div>
<div style="font-size: 11px; color: #aaa;">
Column: ${args.column.title}
</div>
</div>
`;
return true; // return true to indicate custom rendering was applied
};
// Reset to default rendering
board.cardRendering = null;Custom Tooltips
Provide a custom tooltip function to show additional information when hovering over a card.
// The tooltip function receives CardTooltipArgs and returns CardTooltipContent
// CardTooltipContent: { title: string; rows?: { label: string; value: string }[] }
board.cardTooltip = (args) => {
return {
title: args.card.title,
rows: [
{ label: 'Priority', value: args.card.priority },
{ label: 'Tags', value: args.card.tags.join(', ') || '—' },
{ label: 'Weight', value: args.card.weight?.toString() ?? '—' },
],
};
};
// Async tooltips are also supported
board.cardTooltip = async (args) => {
const details = await fetchCardDetails(args.card.id);
return { title: args.card.title, rows: details.rows };
};
// Disable tooltips
board.cardTooltip = null;Assignee Resolver
Cards store assignees as string IDs. Provide an assignee resolver function to map IDs to display names and optional avatar images.
// Returns KanbanAssignee: { name: string; imageUrl?: string; color?: string }
board.assigneeResolver = (id) => {
const users: Record<string, { name: string; imageUrl?: string; color?: string }> = {
alice: { name: 'Alice Johnson', imageUrl: '/avatars/alice.jpg' },
bob: { name: 'Bob Smith', imageUrl: '/avatars/bob.jpg' },
carol: { name: 'Carol Williams' }, // initials will be shown
dave: { name: 'Dave Brown', color: '#e67e22' }, // custom avatar color
};
return users[id] ?? null;
};When imageUrl is provided, the avatar shows the image. Otherwise, initials are derived from the name. The optional color property overrides the default avatar background color.