TimelineKit

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: stringUnique identifier (read-only).
title: stringDisplay name.
color: ColorValue | nullColor index or custom color. null = automatic by position.
wipLimit: number | nullWork-in-progress limit. null = unlimited.
collapsed: booleanWhether the column shows only the card count.
isTerminal: booleanWhether 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: stringUnique identifier (read-only).
columnId: stringID of the column this card belongs to.
swimlaneId: string | nullID of the swimlane (null = unassigned row).
title: stringDisplay title.
description: string | nullOptional description text.
color: ColorValue | nullColor 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 | nullStory points or effort weight.
dueDate: Date | nullDue date.
archived: booleanWhether the card is archived.
data: anyArbitrary 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: stringUnique identifier (read-only).
title: stringDisplay name.
color: ColorValue | nullColor index or custom color. null = automatic.
collapsed: booleanWhether 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 column

Custom 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 }) => { /* ... */ });