List view
Source: atrium/frontend/src/components/ListView.jsx Category: View
List view — a flat table of every task, sortable by any column, optionally grouped (by status, priority, assignee, project). Used when the kanban is too wide or the user wants to scan many tasks at once.
What it is
Section titled “What it is”A CSS grid with a fixed header row and one row per task. Columns are id, title, status, type, assignee, priority, tags, created-at. Clicking a header sorts; click again to reverse. Grouping collapses the table into sections with count headers.
Why it exists
Section titled “Why it exists”The kanban is great for “what’s in flight today”, bad for “have we done anything about rate limiting in the last month”. The list view is for scanning across status boundaries. Same data, different lens.
Code sketch
Section titled “Code sketch”const columns = ['id', 'title', 'status', 'type', 'assignee', 'priority'];
export default function ListView({ tasks }) { const [sortKey, setSortKey] = useState('priority'); const [sortDir, setSortDir] = useState('asc'); const [groupBy, setGroupBy] = useState('none');
const sorted = useMemo(() => [...tasks].sort(compare(sortKey, sortDir)), [tasks, sortKey, sortDir]); const grouped = groupBy === 'none' ? { All: sorted } : groupBy_(sorted, groupBy);
return ( <table> <Header columns={columns} sortKey={sortKey} sortDir={sortDir} onSort={setSortKey} /> {Object.entries(grouped).map(([group, items]) => ( <GroupSection key={group} label={group} count={items.length} items={items} /> ))} </table> );}How it’s used
Section titled “How it’s used”- Atrium — toggle between Board / List / Tree from the top-right view switcher. Preferences persist in localStorage.
- Pattern generalizes to any collection that benefits from both a card view and a table view
Gotchas
Section titled “Gotchas”- Virtualization kicks in around ~200 rows. Below that, plain render is fine; above, scroll performance tanks in non-virtualized tables. Atrium uses
@tanstack/react-virtualwhen task count crosses a threshold. - Sort stability. JS
Array.sortisn’t stable in some older runtimes; modern engines are. If you see tasks shuffling on repeated sorts, convert to a comparator that breaks ties by id. - Column widths are a design decision. Fixed-width columns for id, status, type, assignee; flex column for title. Otherwise a long title pushes everything else off-screen.
- Grouping adds a second axis. When combined with sorting, the user’s mental model is “sort within groups”. Make that explicit; don’t let grouping override sorting silently.
- Row density vs scannability. Dense rows fit more tasks per screen; sparse rows are more readable. Atrium ships one density and lets users tweak via a settings toggle.
- Sticky header matters. Scrolling long lists without a sticky header is unusable.
position: stickyon the header row, notfixed— sticky respects the table’s scroll container.
See also
Section titled “See also”- components/task-card · components/board — the other two primary views
- projects/atrium