Data
Columns
Columns represent workflow stages (e.g. To Do, In Progress, Done). Cards belong to exactly one column at a time.
Column Properties
| id: string | Unique identifier (read-only). |
| title: string | Display name. |
| color: ColorValue | null | Color index or custom color. null = automatic by position. |
| wipLimit: number | null | Work-in-progress limit. null = unlimited. |
| collapsed: boolean | Whether the column shows only the card count. |
| isTerminal: boolean | Whether this is a terminal state (e.g. Done, Closed). |
Adding & Removing Columns
import { KanbanColumn } from '@timelinekit/core';
// Create a column
const col = new KanbanColumn(null); // null = auto-generate ID
col.title = 'In Progress';
col.wipLimit = 3;
col.color = 4;
// Add to the board
board.data.addColumn(col);
// Insert at a specific position
board.data.insertColumn(0, col);
// Access columns
console.log(board.data.columnsLength);
const first = board.data.getColumn(0);
const byId = board.data.getColumnById('some-id');
// Reorder
board.data.moveColumn(col, 2);
// Remove
board.data.removeColumn(col);
// Replace all columns at once
board.data.assignColumns([col1, col2, col3]);From Serialized Data
// Create from a plain object
const col = KanbanColumn.fromAny({
id: 'col-1',
title: 'To Do',
color: 5,
wipLimit: 6,
});
// Serialize back
const data = col.toAny();Cards
Cards are the primary items on the board. Each card belongs to a column and optionally to a swimlane.
Card Properties
| id: string | Unique identifier (read-only). |
| columnId: string | ID of the column this card belongs to. |
| swimlaneId: string | null | ID of the swimlane (null = unassigned row). |
| title: string | Display title. |
| description: string | null | Optional description text. |
| color: ColorValue | null | Color index or custom color. null = inherit from column. |
| priority: CardPriority | 'none' | 'low' | 'medium' | 'high' | 'critical'. Default: 'none'. |
| tags: string[] | Array of tag strings. |
| assigneeIds: string[] | Array of assignee identifiers. |
| weight: number | null | Story points or effort weight. |
| dueDate: Date | null | Due date. |
| archived: boolean | Whether the card is archived. |
| data: any | Arbitrary user data (not serialized). |
Adding & Removing Cards
import { KanbanCard } from '@timelinekit/core';
// Create a card in a specific column
const card = new KanbanCard(null, 'column-id');
card.title = 'Implement authentication';
card.priority = 'critical';
card.tags = ['backend', 'security'];
card.weight = 8;
card.dueDate = new Date(2027, 0, 15);
card.assigneeIds = ['alice', 'bob'];
// Add to the board
board.data.addCard(card);
// Insert at a specific index within the column
board.data.insertCard(card, 0); // first position
// Move to a different column
board.data.moveCard(card, 'done-column-id', 0);
// Query cards
const inColumn = board.data.getCardsInColumn('column-id');
const inSwimlane = board.data.getCardsInSwimlane('swimlane-id');
const count = board.data.getCardCountInColumn('column-id');
const overLimit = board.data.isWipLimitExceeded('column-id');
// Remove
board.data.removeCard(card);
// Replace all cards at once
board.data.assignCards([card1, card2, card3]);Swimlanes
Swimlanes add horizontal grouping to the board (e.g. by team, priority, or category). Cards without a swimlane appear in the "Unassigned" row.
Swimlane Properties
| id: string | Unique identifier (read-only). |
| title: string | Display name. |
| color: ColorValue | null | Color index or custom color. null = automatic. |
| collapsed: boolean | Whether the swimlane shows only the header. |
Adding & Removing Swimlanes
import { KanbanSwimlane } from '@timelinekit/core';
const lane = new KanbanSwimlane(null);
lane.title = 'Frontend';
board.data.addSwimlane(lane);
board.data.insertSwimlane(0, lane);
board.data.moveSwimlane(lane, 2);
board.data.removeSwimlane(lane);
// Access swimlanes
console.log(board.data.swimlanesLength);
const byId = board.data.getSwimlaneById('lane-id');
// Assign a card to a swimlane
card.swimlaneId = lane.id;Checklists
Cards can have checklist items with completion tracking. A progress bar is displayed on the card when checklist items exist.
import { ChecklistItem } from '@timelinekit/core';
// Add checklist items to a card
const item1 = new ChecklistItem(null, 'Write tests');
item1.completed = true;
card.addChecklistItem(item1);
const item2 = new ChecklistItem(null, 'Code review');
card.addChecklistItem(item2);
// Toggle completion
item2.toggle();
// Access checklist
console.log(card.checklistLength); // 2
console.log(card.checklistProgress); // 50 (percent)
const first = card.getChecklistItem(0);
// Reorder & remove
card.moveChecklistItem(item2, 0);
card.removeChecklistItem(item1);Color Resolution
Cards inherit their color from the column when their own color is null. Use getCardColor to resolve the effective color.
// Get the effective color of a card (inherits from column if card.color is null)
const color = board.data.getCardColor(card);
// Override card color
card.color = 3; // explicit color index
card.color = null; // inherit from columnCustom Properties
Columns, cards, and swimlanes support custom properties for storing arbitrary metadata.
// Set a custom property on a card
card.setPropertyValue('estimatedHours', 16);
card.setPropertyValue('department', 'Engineering');
// Read it back
const hours = card.getPropertyValue('estimatedHours'); // 16
// Works on columns and swimlanes too
column.setPropertyValue('owner', 'alice');
swimlane.setPropertyValue('team', 'Platform');Data Events
Subscribe to data changes to sync with a backend or update external UI.
// Column events
board.events.columnAdded$.subscribe(({ column }) => {
console.log('Column added:', column.title);
});
board.events.columnChanged$.subscribe(({ column }) => {
console.log('Column changed:', column.title);
});
board.events.columnRemoved$.subscribe(({ column }) => {
console.log('Column removed:', column.title);
});
board.events.columnMoved$.subscribe(({ column, fromIndex, toIndex }) => {
console.log('Column moved from', fromIndex, 'to', toIndex);
});
// Card events
board.events.cardAdded$.subscribe(({ card }) => { /* ... */ });
board.events.cardChanged$.subscribe(({ card }) => { /* ... */ });
board.events.cardRemoved$.subscribe(({ card }) => { /* ... */ });
board.events.cardMoved$.subscribe(({ card, fromColumnId, toColumnId, toIndex }) => {
console.log('Card moved from', fromColumnId, 'to', toColumnId);
});
// Swimlane events
board.events.swimlaneAdded$.subscribe(({ swimlane }) => { /* ... */ });
board.events.swimlaneChanged$.subscribe(({ swimlane }) => { /* ... */ });
board.events.swimlaneRemoved$.subscribe(({ swimlane }) => { /* ... */ });
board.events.swimlaneMoved$.subscribe(({ swimlane, fromIndex, toIndex }) => { /* ... */ });