Roadmap
What is left to build, in what order, and which parts need designing before they can be coded.
This is the build plan, derived from surveying shadcn/ui (63 components), Atlassian (~70) and Polaris (~80), then diffing against both this codebase and the Figma library.
Where we are
Every non-icon component in the Figma library is now coded, along with the ten that had to be designed first. Each has a page, a live demo and a registry item.
What remains is the lower-priority tail — components that exist in other systems but not in this Figma file, listed at the end of Phase 3.
Phase 1 — designed in Figma, needs code only
Done. All of it, grouped into files so the docs stay navigable rather than sprawling to one page per component.
1a · Table and rows
| Component | Figma | Notes |
|---|---|---|
| Table Row | 177:776 | Default / Hover / Selected. A generic row, unlike the fixed GRID_COLS grid |
| Table Header Cell | 177:673 | Default / Sorted. Replaces the hand-rolled SortHeader in Exchange |
| Selectable Row | 476:525 | Unselected / Selected / Hover |
| Row Actions | 779:660 | The trailing action cluster, currently rebuilt per screen |
| Numbered Row | 471:488 | Ordered list item with a real number column |
| Group Header | 424:415 | Section label inside a list |
1b · Chips, tiles and small display
| Component | Figma | Notes |
|---|---|---|
| Metric Tile | 649:566 | A compact stat — smaller than InsightCard |
| Avatar Cluster | 654:571 | Overlapping faces in a 40px footprint, distinct from AvatarGroup |
| Inline Chip | 455:448 | A chip that sits inside a line of prose |
| Link Chip | 471:476 | A URL rendered as a chip |
| Suggestion Chip | 663:640 | A tappable prompt suggestion |
| Icon Frame | 471:460 | 40px framed icon, the larger sibling of IconTile |
| Accent Button | 170:637 | Brand / Ink / Violet / Danger × four states |
| Day Ring | 649:606 | Complete / Partial / Empty — a day's completion |
| Status Item | 662:631 | Active / Idle activity line |
| Nav Item | 662:618 | Plain / Badge sidebar entry |
| Nav Progress | 482:2285 | "Getting started · 1 of 5" |
| Trial Footer | 482:2295 | "14 days left · Upgrade" |
1c · Files and attachments
| Component | Figma | Notes |
|---|---|---|
| Dropzone | 204:1416 | Idle / Active / Error. The one genuinely missing file primitive |
| Attachment Thumbnail | 207:1445 | Image / Add |
| Audio Attachment | 206:1502 | With a scrub bar and duration |
| Scrim | 88:352 | The overlay wash, currently inlined in Modal and CommandK |
| Sheet Header | 663:650 | The grabber-and-title row for mobile sheets |
1d · Mail and merge
| Component | Figma | Notes |
|---|---|---|
| Recipient Field | 456:439 | A TO field holding recipient chips |
| Recipient Chip | 455:458 | Avatar plus name |
| Merge Field | 455:447 | Mapped / Missing — a mail-merge token |
| Message Actions | 427:398 | Copy / regenerate / share, currently inlined in Assistant |
| History Row | 21:14 | Default / Active conversation entry |
| Mobile Row | 657:604 | Navigate / Toggle — a settings row |
Phase 2 — the AI and agent set
Done — see Agent set. Called out separately because it is the part of this library the big systems do not have: shadcn only added its AI primitives recently, and neither Atlassian nor Polaris ship anything equivalent.
| Component | Figma | Notes |
|---|---|---|
| Composer | 115:532 | Suggestion chips over an input — the Assistant screen fakes this today |
| Prompt Field | 663:624 | The single-line ask |
| Prompt Tile | 427:433 | A starter card with a title and description |
| Model Picker | 424:414 | Default / Open / Hover |
| Tool Call | 428:457 | Running / Done / Error — what the agent did, and how long it took |
| Transcript Row | 477:526 | Speaker, timestamp and utterance |
| Source Row | 662:632 | A grounded source with a citation count |
StreamingIndicator is already shipped and belongs to this set.
Phase 3 — needs designing in Figma first
Done. All ten were designed into the Figma library (page Components, group
Structure), then coded and documented. Every fill is bound to a token — the
components carry no raw colours.
Tabs and Spinner were promotions: both already existed in the codebase, stranded
inside messages.tsx and exchange.tsx.
| Component | Figma | Status |
|---|---|---|
| Empty state | 1004:699 | shipped |
| Breadcrumb | 1004:709 | shipped |
| Pagination | 1005:695 | shipped |
| Stepper | 1005:713 | shipped |
| Accordion | 1005:737 | shipped |
| Popover | 1006:695 | shipped |
| Slider | 1006:703 | shipped |
| Drawer | 1006:714 | shipped |
| Spinner | promoted | shipped |
| Tabs | 12:11 | shipped |
The screens now use them. The approval chain in Purchase requests is a
Stepper, the Previous/Next in Spend insights is a Pagination, and the
hand-rolled empty states in Purchase requests, Exchange (twice), Spend insights
and Tasks are all EmptyState.
Two were deliberately left alone. The Assistant's action row and composer match
their own Figma screen — three buttons and an external send — while the
standalone MessageActions has four different buttons and Composer has no
external send. They are different components for different places, and swapping
one in would have broken the screen's fidelity.
The narrow cases were also left: the "Nothing matches" line inside a dropdown
and the command palette's no-results line. An EmptyState card inside a menu is
the wrong shape.
Lower priority, same category: Combobox, Context menu, Hover card, Toggle group, Date picker, Scroll area, Button group, Code block, Inline edit, Carousel, Input OTP, Rating, Resizable, Tree view.
Order
- Phase 3's promotions first — Tabs and Spinner already exist in the codebase and only need lifting into primitives. Cheapest possible wins, and they unblock other work.
- Phase 1a and 1b — the highest-reuse items, and several replace code that is currently duplicated per screen.
- Phase 2 — the differentiated set.
- The rest of Phase 3 — genuine design work, one at a time.
The rule that governs all of it
Where a component exists in Figma, it gets ported — not reinvented. This session
has already produced two components that were hand-rolled inside screens while
the real design sat in the library: the Exchange transaction modal had its own
DetailRow, and Spend insights had its own selection bar. Both were replaced
once the library was actually checked.
The cost of not checking is not a wasted afternoon. It is a system whose code and design quietly disagree.