refactor(desktop): frame Issues, the issue board and Factory with the toolbar page frame
Merged
CH
7d ago+310+310+012345678901234567890123456789-162-162-012345678901234567890123456789
Follow-up to the design-system migration. #3415 (FX1) added PAGE_FRAME.TOOLBAR and PAGE_WIDTH to CollectionPage after D37, D40 and D42 had already shipped their own toolbar-and-scroll frames. This PR moves those three screens onto the shared frame.
What
- Issues list (
issues-page.tsx):CollectionPagewithframe={PAGE_FRAME.TOOLBAR}andlabel="Issues". The existing.desktop-toolbarheader is passed in astoolbar. The list stands at the page's measure (PAGE_WIDTH.MEASURE). The page now owns the loading, empty ("No issues yet") and failed (Retry) states, throughstate/empty/error. - Issue board: the same page with
PAGE_WIDTH.FULL, so the page scrolls the board sideways..issue-board-scrollis removed. When the arrow keys move to a column, the code now finds the sideways scroller by its computedoverflow-xinstead of by a desktop class, and takes the inset from where the board starts. - Factory (
desktop-factory.tsx): the line is aCollectionPagewithPAGE_WIDTH.FULLunder the toolbar..factory-scrollis removed. The stations'factorycontainer query moves to a new.factory-boardwrapper. A chosen world still stands in its own.factory-viewsection under the same toolbar, because a world is a full-bleed scene, not a collection. - The arrow keys and row motion are still read against one root:
.issues-pages(now held in state) and a new.factory-pages(display: contents). - Shared (
collection-page.css): withPAGE_WIDTH.FULL, the content now holds to the page's height (flex: 1 1 0; min-height: 0). Without this, the board's columns would grow to fit their cards and the whole page would scroll down. Its bottom inset is now a trailing::afteritem instead of padding, so content taller than the page (Factory's line) keeps it. The only other caller is the catalog's board example, whose columns are short. - Rows keep
line-height: normalinside.issue-groups,.issue-boardand.factory-board, as Home draws the same rows, so the page's 13/20 body leading doesn't make them taller. - Two empty-state choices: an empty board still shows its columns (READY), and while the read is out the board and Factory show nothing, as before. The shared loading rows are shaped like a list, not like a board or Factory's stations.
Visible changes (contract cleanups)
- Page inset is the contract's 40px (24px under 480px of room) instead of 20px, on all three screens. As a result, with the sidebar collapsed in a 1280px window, the board's fifth column now runs past the edge and the board scrolls sideways sooner.
- Bottom inset is 40px instead of 32px (list and Factory) or 16px (board), so the board's columns end 24px higher.
- The list stands at the page's measure (720px) instead of Home's 600px column.
- While the issues list is read, it shows the shared loading rows (named "Reading issues") instead of nothing.
- Factory's summary line starts 16px below the toolbar's hairline instead of 12px. Under a failure banner it keeps its 12px gap.
- No top fade: the list's and Factory's content no longer fades in at the top edge as it scrolls (
.scroll-fade-top), because the shared page draws no fade. - Factory's narrow layout (stations stacked) now triggers at 960px of content room measured inside the 40px insets, so it switches 40px of window width earlier.
Tests
- New:
issues-page.test.tschecks that while the issues are read, the list shows the "Reading issues" status and the board shows none. Each then draws its issues. The test fails without this change. - Updated: the board's keep-in-view test lays out the page's scroll (
.luke-collection-page-scroll,overflow-x: autoviagetComputedStyle) instead of.issue-board-scroll. Factory's empty-state test checks that no button stands outside the toolbar. Its unread test reads.factory-board. The world picker's "board stands" helper reads the Factory region with no world drawn. pnpm check:affectedexits 0.
Screenshots
Captured on Linux with headless Chrome at 1280Ć840, sidebar collapsed, the way #3420 was. A throwaway, uncommitted jsdom test rendered the real pages with synthetic data. Chrome then painted them in .desktop-shell > main.desktop-main with the desktop stylesheet built from main (before) and from this branch (after).
| Before | After | |
|---|---|---|
| Board, light | ![]() | ![]() |
| Board, dark | ![]() | ![]() |
| List, light | ![]() | ![]() |
| List, dark | ![]() | ![]() |
| Factory, light | ![]() | ![]() |
| Factory, dark | ![]() | ![]() |
| Factory empty, light | ![]() | ![]() |
Not verified on a Mac
- The toolbar's drag region and no-drag controls inside
CollectionPage. The toolbar element is unchanged; only its parent changed. - Trackpad sideways scrolling on the board, dragging a card while the page is scrolled sideways, and overlay scrollbars against
scrollbar-gutter: stable. - A Factory world picked from the toolbar. Its frame is unchanged apart from the wrapper.
š¤ Generated with Claude Code













