Board & Views
Last updated on 2026-03-26
The board and views module provides five different ways to visualize and manage project tasks. Each view shares the same underlying task data but presents it optimized for different workflows. All views include a ViewSwitcher component for quick navigation between them, along with a shared FilterBar for filtering by status, priority, assignee, and labels. All screens are nested under projects/[id]/ in the (dashboard) route group.
Kanban Board
Route: /projects/[id]/board
The Kanban board is the hero feature of the Kanban PM Kit. It provides a visual, drag-and-drop interface for managing tasks across status columns.
- Drag-and-drop -- powered by
@hello-pangea/dnd, task cards can be dragged between columns to update their status - Status columns -- Backlog, Todo, In Progress, In Review, Done, and Cancelled, each with a distinct color indicator
- Task cards -- each card shows task ID badge (e.g. KAN-42), title, assignee avatar, priority icon, due date, and label badges
- Column headers -- each column header displays the status name, task count, and a "+" button for quick task creation via
QuickAddCard - Quick add -- inline card creation at the bottom of any column; type a title and press Enter to create a task with that column's status
- Filter bar -- multi-select filters for priority, assignee, and labels; filters persist across view switches
- Group by -- toggle between grouping by Status (default), Priority, Assignee, or Label
- Card actions -- click a card to navigate to the task detail page; hover to reveal a quick actions menu (Edit, Change Priority, Assign, Delete)
import { KanbanBoard } from "@/components/kanban/kanban-board"
import { KanbanColumn } from "@/components/kanban/kanban-column"
import { KanbanCard } from "@/components/kanban/kanban-card"
import { ColumnHeader } from "@/components/kanban/column-header"
import { QuickAddCard } from "@/components/kanban/quick-add-card"
import { FilterBar } from "@/components/project/filter-bar"
import { ViewSwitcher } from "@/components/project/view-switcher"
Kanban Board Layout
+----------+----------+----------+----------+----------+----------+
| Backlog | Todo | In Prog | In Rev | Done | Cancel |
| 8 | 5 | 4 | 2 | 12 | 1 |
+----------+----------+----------+----------+----------+----------+
| +------+ | +------+ | +------+ | +------+ | +------+ | +------+ |
| |KAN-01| | |KAN-05| | |KAN-12| | |KAN-18| | |KAN-03| | |KAN-22| |
| |Task | | |Task | | |Task | | |Task | | |Task | | |Task | |
| |title | | |title | | |title | | |title | | |title | | |title | |
| +------+ | +------+ | +------+ | +------+ | +------+ | +------+ |
| +------+ | +------+ | +------+ | +------+ | +------+ | |
| |KAN-02| | |KAN-06| | |KAN-13| | |KAN-19| | |KAN-04| | |
| +------+ | +------+ | +------+ | +------+ | +------+ | |
| [+ Add] | [+ Add] | [+ Add] | [+ Add] | [+ Add] | [+ Add] |
+----------+----------+----------+----------+----------+----------+
Kanban Board Architecture
The Kanban board uses a three-tier component hierarchy built on @hello-pangea/dnd:
KanbanBoard (DragDropContext)
+-- KanbanColumn (Droppable) x 6 statuses
| +-- ColumnHeader (status name, count, add button)
| +-- KanbanCard (Draggable) x N tasks
| | +-- TaskIdBadge (e.g. KAN-42)
| | +-- Task title
| | +-- MemberAvatar (assignee)
| | +-- TaskPriority (icon)
| | +-- DateBadge (due date)
| | +-- TaskLabels (label badges)
| +-- QuickAddCard (inline create)
+-- onDragEnd handler (updates task status in state)
How it works:
-
KanbanBoardwraps the entire board in aDragDropContextand manages theonDragEndcallback. When a card is dropped, it reads thesourceanddestinationfrom the result, removes the task from the source column, inserts it into the destination column at the correct index, and updates the task'sstatusfield. -
Each
KanbanColumnis aDroppablecontainer identified by itsstatusId. It receives the filtered list of tasks for that status and renders them as an ordered list. TheColumnHeaderdisplays the status name, task count, and add button. -
Each
KanbanCardis aDraggableidentified by thetaskId. It renders a card with task summary information. Theprovided.draggablePropsandprovided.dragHandlePropsare spread onto the card element, andprovided.innerRefis used as the ref callback.
// kanban-board.tsx (simplified)
import { DragDropContext, type DropResult } from "@hello-pangea/dnd"
function KanbanBoard({ tasks, statuses }: KanbanBoardProps) {
const [columns, setColumns] = useState(groupTasksByStatus(tasks, statuses))
function onDragEnd(result: DropResult) {
const { source, destination } = result
if (!destination) return
if (source.droppableId === destination.droppableId && source.index === destination.index) return
// Move task between columns
const sourceColumn = [...columns[source.droppableId]]
const [movedTask] = sourceColumn.splice(source.index, 1)
movedTask.status = destination.droppableId as TaskStatusType
const destColumn = source.droppableId === destination.droppableId
? sourceColumn
: [...columns[destination.droppableId]]
destColumn.splice(destination.index, 0, movedTask)
setColumns({
...columns,
[source.droppableId]: sourceColumn,
[destination.droppableId]: destColumn,
})
}
return (
<DragDropContext onDragEnd={onDragEnd}>
{statuses.map((status) => (
<KanbanColumn key={status.id} status={status} tasks={columns[status.id]} />
))}
</DragDropContext>
)
}
Data Sources
| Data | Source | Location |
|---|---|---|
| Tasks | tasks (filtered by projectId) |
data/seed.ts |
| Task statuses | taskStatuses |
data/seed.ts |
| Team members | teamMembers |
data/seed.ts |
| Labels | taskLabels |
data/seed.ts |
List View
Route: /projects/[id]/list
A structured table view of all project tasks with grouping, sorting, and inline editing.
- Task rows -- tabular rows using
TaskRowcomponent showing task ID badge, title, status badge, priority icon, assignee avatar, due date, labels, and estimate - Group headers -- collapsible
GroupHeadersections that organize tasks by status (default), priority, assignee, or label - Inline status toggle -- click the status badge on any row to cycle through statuses
- Inline priority select -- click the priority icon to open a dropdown and change priority
- Sorting -- click column headers to sort by title, status, priority, assignee, due date, or created date
- Bulk actions -- checkbox selection for multi-task operations: change status, change priority, assign, add labels, or delete
- Filter bar -- shared
FilterBarcomponent with status, priority, assignee, and label multi-select filters
import { TaskRow } from "@/components/task/task-row"
import { GroupHeader } from "@/components/project/group-header"
import { FilterBar } from "@/components/project/filter-bar"
import { ViewSwitcher } from "@/components/project/view-switcher"
List View Layout
+------+-------------------+----------+--------+----------+--------+-------+
| [x] | Task | Status | Prior. | Assignee | Due | Est. |
+------+-------------------+----------+--------+----------+--------+-------+
| --- In Progress (4) ---------------------------------------------------- |
| [ ] | KAN-12 Setup auth | In Prog | High | [Sarah] | Mar 20 | 5 |
| [ ] | KAN-13 API routes | In Prog | Medium | [Mike] | Mar 22 | 3 |
+------+-------------------+----------+--------+----------+--------+-------+
| --- Todo (5) ----------------------------------------------------------- |
| [ ] | KAN-05 Dashboard | Todo | High | [Lisa] | Mar 25 | 8 |
| [ ] | KAN-06 Sidebar | Todo | Low | [--] | -- | 2 |
+------+-------------------+----------+--------+----------+--------+-------+
Data Sources
| Data | Source | Location |
|---|---|---|
| Tasks | tasks (filtered by projectId) |
data/seed.ts |
| Team members | teamMembers |
data/seed.ts |
| Labels | taskLabels |
data/seed.ts |
Backlog
Route: /projects/[id]/backlog
A prioritized backlog view showing tasks not yet assigned to a cycle, designed for sprint planning.
- Backlog tasks -- list of
TaskRowcomponents for tasks with nocycleId, showing task ID badge, title, priority, estimate, labels, and assignee - Priority ordering -- tasks are sorted by priority (Urgent first, then High, Medium, Low, None) and within priority by creation date
- Drag to cycle -- if cycles are enabled, the page shows the active cycle panel on the right; drag tasks from the backlog to add them to the current sprint
- Estimate totals -- header shows the total estimate points in the backlog and the remaining capacity in the active cycle
- Bulk assign to cycle -- checkbox selection and "Add to Cycle" action to move multiple tasks at once
- Filter bar -- filter by priority, assignee, and labels
- Empty state -- contextual message when the backlog is empty, suggesting task creation
import { TaskRow } from "@/components/task/task-row"
import { FilterBar } from "@/components/project/filter-bar"
import { CycleCard } from "@/components/pm/cycle-card"
Backlog Layout
+----------------------------------+---------------------+
| Backlog (24 tasks, 96 pts) | Active Cycle |
+----------------------------------+ Sprint 5 |
| [x] KAN-42 Implement search [H] | Mar 10-24 |
| [ ] KAN-43 Add filters [M] | 12 tasks, 48 pts |
| [ ] KAN-44 Export feature [L] | ████████░░ 72% |
| [ ] KAN-45 User settings [L] | Remaining: 13 pts |
| ... | |
| [Add to Cycle] | |
+----------------------------------+---------------------+
Data Sources
| Data | Source | Location |
|---|---|---|
| Tasks | tasks (filtered by projectId, cycleId = null) |
data/seed.ts |
| Active cycle | cycles (filtered by projectId, status = Active) |
data/seed.ts |
Calendar View
Route: /projects/[id]/calendar
A month-view calendar displaying tasks plotted by their due date.
- Month grid -- standard calendar grid showing the current month with day cells; tasks appear as colored chips within their due date cell
- Task chips -- compact chips showing task title truncated to fit, color-coded by priority (Urgent = red, High = orange, Medium = blue, Low = gray)
- Click to detail -- clicking a task chip navigates to the task detail page
- Day click -- clicking an empty day cell opens the quick task creation form pre-filled with that due date
- Month navigation -- previous/next month arrows and a "Today" button to jump to the current month
- Filter bar -- filter displayed tasks by status, priority, assignee, and labels
- Overflow indicator -- when more than 3 tasks fall on a single day, a "+N more" link expands to show all tasks in a popover
import { Calendar } from "@/components/ui/calendar"
import { FilterBar } from "@/components/project/filter-bar"
import { ViewSwitcher } from "@/components/project/view-switcher"
Calendar Layout
+-----+-----+-----+-----+-----+-----+-----+
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
+-----+-----+-----+-----+-----+-----+-----+
| | | | | 1 | 2 | 3 |
| | | | |[T1] | | |
+-----+-----+-----+-----+-----+-----+-----+
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| |[T2] | |[T3] |[T4] | | |
| |[T5] | | |[T6] | | |
| | | | |+2 | | |
+-----+-----+-----+-----+-----+-----+-----+
Data Sources
| Data | Source | Location |
|---|---|---|
| Tasks | tasks (filtered by projectId, dueDate != null) |
data/seed.ts |
Timeline / Gantt
Route: /projects/[id]/timeline
A Gantt chart timeline view showing tasks as horizontal bars plotted against a date axis, with milestone markers and dependency visualization.
- Gantt chart -- horizontal timeline built with the
GanttChartcomponent, showing tasks as colored bars spanning fromstartDatetodueDate - Gantt bars -- each
GanttBarrepresents a task, color-coded by status; bar width represents duration; hover shows task details tooltip - Today marker -- red vertical line via
TodayMarkerindicating the current date on the timeline - Milestone markers -- diamond-shaped
MilestoneMarkercomponents positioned on the date axis for project milestones - Task list sidebar -- left-side panel listing tasks with title, assignee, and status for reference alongside the chart
- Zoom controls -- toggle between Day, Week, and Month zoom levels to adjust the timeline granularity
- Scroll sync -- the task list sidebar and Gantt chart scroll vertically in sync
- Filter bar -- shared filter controls for status, priority, assignee, and labels
import { GanttChart } from "@/components/timeline/gantt-chart"
import { GanttBar } from "@/components/timeline/gantt-bar"
import { MilestoneMarker } from "@/components/timeline/milestone-marker"
import { TodayMarker } from "@/components/timeline/today-marker"
import { FilterBar } from "@/components/project/filter-bar"
import { ViewSwitcher } from "@/components/project/view-switcher"
Timeline Layout
+------------------+------------------------------------------+
| Task List | Mar 2026 |
| | 10 11 12 13 14 15 16 17 18 19 |
+------------------+-----|-----|-----|-----|-----|-----|-------+
| KAN-01 Auth | ███████████████ |
| KAN-02 API | ████████████████ |
| KAN-03 Dashboard | ████████████ |
| KAN-04 Settings | ████████ |
| -- Milestone -- | [*] v1.0 Beta |
| | | (today) |
+------------------+------------------------------------------+
Gantt Chart Architecture
The timeline is built from four composable components:
GanttChart (container)
+-- Date axis header (days/weeks/months based on zoom)
+-- TodayMarker (red vertical line at current date)
+-- GanttBar x N tasks
| +-- Colored bar (width = duration, left offset = start date)
| +-- Tooltip on hover (task title, dates, assignee, status)
+-- MilestoneMarker x N milestones
+-- Diamond icon positioned on milestone date
+-- Label text
Data Sources
| Data | Source | Location |
|---|---|---|
| Tasks | tasks (filtered by projectId, startDate != null) |
data/seed.ts |
| Milestones | milestones (filtered by projectId) |
data/seed.ts |
View Switcher
The ViewSwitcher component appears at the top of all five view pages, providing one-click navigation:
import { ViewSwitcher } from "@/components/project/view-switcher"
<ViewSwitcher
projectId={projectId}
currentView="board"
views={["board", "list", "backlog", "calendar", "timeline"]}
/>
Each view button shows an icon and label. The active view is highlighted with the primary color. The switcher includes proper aria-current="page" on the active button for screen reader support.
Next Steps
- Cycles & Modules -- sprint cycles, modules, and pages
- Tasks -- task detail, comments, and subtasks
- Dashboard & Activity -- workspace dashboard and activity feed