Skip to content

Your First Kanban Board

Create a small working board before adding rules, forms or remote data. The example uses the same task cards throughout these guides.

Interactive example

Your first board

Four tasks move through To do, In progress and Done.

Try it: Move the research card, or double-click a card to edit it.

Loading example…

What to notice: Moving a card changes its status; the board keeps the same four tasks.

TypeScript source

Install the packages from Getting Started, then use this source in your app.

first-board.ts
import { defineCustomElements } from '@revolist/revogrid/loader';
import { KanbanPlugin, type KanbanConfig } from '@revolist/kanban';
import '@revolist/revogrid-pro/styles.css';
import '@revolist/kanban/styles.css';
export interface WorkCard {
id: string; title: string; status: string; order: number;
description?: string; team?: string; owner?: string; priority?: string;
tags?: string[]; progress?: number; startDate?: string; endDate?: string;
}
export const demoCards: WorkCard[] = [
{ id: 'task-1', title: 'Research customer needs', description: 'Collect feedback for the next release.', status: 'todo', team: 'product', owner: 'Ana', priority: 'normal', order: 1000 },
{ id: 'task-2', title: 'Build onboarding', description: 'Make the first session useful.', status: 'doing', team: 'product', owner: 'Mia', priority: 'high', order: 1000 },
{ id: 'task-3', title: 'Improve API errors', description: 'Return actionable validation messages.', status: 'todo', team: 'platform', owner: 'Rui', priority: 'normal', order: 2000 },
{ id: 'task-4', title: 'Release checklist', description: 'Ready for the next deployment.', status: 'done', team: 'platform', owner: 'Sam', priority: 'normal', order: 1000 },
];
export const boardConfig: KanbanConfig<WorkCard> = {
columns: [{ prop: 'todo', name: 'To do', size: 210 }, { prop: 'doing', name: 'In progress', size: 210 }, { prop: 'done', name: 'Done', size: 210 }],
card: { titleField: 'title' }, cardRowHeight: 88,
addCard: false, swimlaneColumn: false,
};
export async function configureBoard(
grid: HTMLRevoGridElement,
config: KanbanConfig<WorkCard> = boardConfig,
cards: readonly WorkCard[] = demoCards,
extraPlugins: HTMLRevoGridElement['plugins'] = [],
) {
await defineCustomElements();
grid.plugins = [KanbanPlugin, ...extraPlugins]; // The packaged editor and history install automatically.
grid.columns = [{ prop: 'title', name: 'Title' }, { prop: 'status', name: 'Status' }, { prop: 'owner', name: 'Owner' }];
// Cached remote data can hydrate immediately: finish initial grid setup first.
grid.kanban = config.remote ? { ...config, remote: false } : config;
grid.source = cards.map(card => ({ ...card }));
await grid.componentOnReady();
const plugins = await grid.getPlugins();
const kanban = plugins.find((plugin): plugin is KanbanPlugin<WorkCard> => plugin instanceof KanbanPlugin);
if (!kanban) throw new Error('Kanban could not start.');
if (config.remote) grid.kanban = config;
return kanban;
}
// Give your container a width and mount once after it exists in the DOM.
export async function createKanbanBoard(container: HTMLElement) {
await defineCustomElements();
const grid = document.createElement('revo-grid');
grid.style.cssText = 'display:block;width:100%;height:400px';
container.append(grid);
try {
const kanban = await configureBoard(grid);
return { grid, kanban, destroy() { grid.remove(); } };
} catch (error) { grid.remove(); throw error; }
}
Download first-board.ts

Try it: move a card from To do to In progress, then Reset. Double-click a card to open the packaged editor.

Terminal window
pnpm add @revolist/revogrid @revolist/revogrid-pro @revolist/kanban
import '@revolist/revogrid-pro/dist/revogrid-pro.css';
import '@revolist/kanban/styles.css';

Open the example’s TypeScript source and download first-board.ts. The live example imports the same source; it includes the card data, field mapping, plugin registration and cleanup.

Call its exported helper from your browser application:

import { createKanbanBoard, boardConfig } from './first-board';
const host = document.createElement('div');
document.body.append(host);
const board = await createKanbanBoard(host);
const { grid, kanban } = board;
const config = boardConfig; // The plain configuration used in later recipes.
// On application cleanup: board.destroy();

The helper returns the grid and public Kanban plugin. Replace demoCards with your records, then map different field names in Card Data and Field Mapping.

Alternative: inline single-card TypeScript setup
import { defineCustomElements } from '@revolist/revogrid/loader';
import { KanbanPlugin, type KanbanConfig } from '@revolist/kanban';
import '@revolist/revogrid-pro/styles.css';
import '@revolist/kanban/styles.css';
defineCustomElements();
await customElements.whenDefined('revo-grid');
const kanban: KanbanConfig = {
columns: [
{ prop: 'todo', name: 'To do' },
{ prop: 'doing', name: 'In progress', wipLimit: 3 },
{ prop: 'done', name: 'Done' },
],
card: { titleField: 'title', descriptionField: 'description' },
};
const grid = document.createElement('revo-grid');
grid.style.cssText = 'display:block;height:600px;width:100%';
grid.plugins = [KanbanPlugin];
grid.kanban = kanban;
document.body.append(grid);
grid.source = [
{ id: 'card-1', title: 'First card', status: 'todo', order: 1000 },
];
// Call when the host view unmounts.
export const destroy = () => grid.remove();

The packaged editor is installed automatically. Double-click a card to edit it; set grid.kanbanCardEditorDialog = false only when supplying your own editor.

Install KanbanToolbarPlugin alongside KanbanPlugin for card actions, search, field filters, undo/redo and board/table switching. The toolbar uses the same editor, canonical cards and persistence adapter as other interactions.

React integration

Add react, react-dom, their TypeScript types and @revolist/react-datagrid. Include the following JSX augmentation to type the kanban property in your application.

import { useMemo } from 'react';
import { RevoGrid } from '@revolist/react-datagrid';
import { KanbanPlugin, type KanbanConfig } from '@revolist/kanban';
import '@revolist/revogrid-pro/styles.css';
import '@revolist/kanban/styles.css';
declare module '@revolist/revogrid' {
namespace JSX {
interface RevoGrid {
kanban?: KanbanConfig<any> | false;
}
}
}
type Card = { id: string; title: string; status: string; order: number };
export default function Board({ rows }: { rows: Card[] }) {
const plugins = useMemo(() => [KanbanPlugin], []);
const kanban = useMemo<KanbanConfig>(() => ({
columns: [{ prop: 'todo', name: 'To do' }, { prop: 'done', name: 'Done' }],
card: { titleField: 'title' },
}), []);
return <RevoGrid style={{ height: '600px', width: '100%' }}
plugins={plugins} kanban={kanban} source={rows} />;
}

Pass rows={[]} for an empty board; replace rows when application data arrives. React owns mounting and unmounting the grid. The standalone Kanban showcase also includes Vue and Angular examples.

The default fields are id, status, and order. Configure idField, columnField, or orderField when your application uses other names.

columns is optional so Kanban can be enabled before workflow metadata or data loads. An empty configuration and empty source render a stable empty board. If cards arrive before columns, they remain visible in the managed Unmapped column until the workflow configuration is supplied.

Continue with Cards, Swimlanes and WIP and the Toolbar.

  • Give the grid an explicit height and import both Pro and Kanban styles.
  • Put application cards in grid.source, not the projected board rows.
  • Match each card status to a workflow prop; labels may be different.
  • Keep card IDs unique and stable. Invalid IDs remain visible but cannot move.
  • Remove the grid when your view unmounts so listeners and loading owners are released.

Next, learn card fields, columns and swimlanes. See the Kanban API for exact types.