feat(ui): add a toolbar-framed variant to CollectionPage and DetailPage
What
A finite frame variant for CollectionPage (F37) and DetailPage (F38), so desktop screens that sit under the window's toolbar (Issues, Inbox, Factory, Automations, an issue's page) can adopt them. Found by D37 (#3414 stack). No screen migrates here; D41+ adopt it.
PAGE_FRAME = { PAGE, TOOLBAR }(newpage-framemodule, exported from@luke/ui).PAGEis the default, so every existing caller is unchanged.TOOLBAR: no in-page title header. The caller hands its window toolbar intoolbar(optional, for a window that draws it elsewhere), which the page stands still above its scroll, and alabel: string, the toolbar's title, which names the region (aria-label).title/description/actionsare typedneverunder it, so the two headings cannot be mixed.- The page still owns content width, the loading/empty/error states, filters (CollectionPage), the secondary column (DetailPage), and the scroll boundary below the toolbar. Content opens a section gap (16px) below the toolbar's hairline, inside the scroll.
PAGE_WIDTH = { MEASURE, FULL }.MEASUREis the default.FULLstands content across the room at the page inset and lets the content scroll sideways, for a board.
Visible changes
None for existing callers. The new variants are shown only in the catalog's new sections ("Under the window's toolbar" on both pages, and "A board across the room, scrolling sideways" on the collection page). The catalog's toolbar is a stand-in for the desktop's.
Tests
jsdom, through the public API: under the toolbar the region is named by its label, has no h1 of its own, and shows the toolbar and its act. Every collection state shows what it says, and the toolbar and filters stay the same elements across state changes. The detail page keeps its secondary landmark.
Screenshots
Catalog, desktop profile, 1280 wide (the new sections are at the bottom of each).
collection page dark

collection page light

detail page dark

detail page light

Not verified
Not verified on a Mac. The desktop's real toolbar (its drag region and window controls) isn't mounted here, so the first adopting D row checks it.
š¤ Generated with Claude Code