refactor(desktop): migrate settings navigation and page frame onto the design system
D13 of the design-system migration (Desktop stack, base feature/desktop-d12-toast-presentation, #3380).
The branch has main merged in. Its diff against main covers only D13's files.
What
- Every Settings page now uses
@luke/ui'sSettingsPage. F40 had moved only Appearance and This Mac. The gate it added (drawnInSettingsPage) is removed. Profile, Workspace, Coding agents, Integrations, Voice, Notifications, Experimental, About, and Keyboard shortcuts now get their inset, title (h1, title role), the reset at the end of the title line, and the 32px gap between groups (--luke-settings-section-gap) from the shared page. - The plan template's reading state (title only, while the template loads) uses the same
SettingsPage.aria-busymoves to the page's section while the read is out. The template's document itself belongs to D30. - The page still re-keys on every page turn, so a page you turn to opens at its top. Search landing is unchanged: same anchors and the same
scrollIntoView. The scroller'sscroll-padding-topis still the page inset, which is now 24px when the pane is narrower than 480px, matching the column. - App-level container layout on the shared page (
desktop.css):- the page fills the room under the drag strip and fades at its top, as F40 set up;
- the sections box is the
settingscontainer that the legacy rows' narrow-width wrap reads (@container settings), at the same width as the old.settingscolumn; - a page with reads still outstanding (
.settings-reading) hides its sections until they all answer; - Experimental's empty state fills the room under the title, at the page's measure.
- Settings navigation: the page list, its group headings, the Back row, the search well, and the results rules now read the
--luke-*role tokens their legacy names aliased, so the values are identical. The rows staysidebar-item, the same row the tasks' sidebar keeps (D04). The search well stays the shared well D08 kept. Its nested 24px clear button stays bespoke, since the 30pxIconButtonwould visibly enlarge it. - Removed, now unused:
.settings(the window's settings column and its container),.settings-page-title,.settings-page-scroll(and its empty-state rules),.settings-page-head,.settings-page-scroll .settings, and thedrawnInSettingsPagegate. - Kept for later rows: the pages' groups still use the desktop's
SettingsGroup(.settings-group/.settings-card). Their rows rely on.settings-card > …selectors, and the bespoke rows and each page are D14–D35. No caller here imported@luke/ui/compat.
Visible changes
- Pages that weren't on the shared frame yet now open with the title 8px lower, because the page inset is now 40px all round (it was 32px above the title). Below a 480px page width the inset narrows to 24px, as the contract says. Appearance and This Mac already looked like this.
- The plan template's loaded document keeps its own head (
.task-page-head, 32px above). D30 aligns it. - Nothing else is intended to change: same title type (22/30, 700), group gap (32px), measure (640px), and navigation look.
Tests
desktop-settings.test.tsfinds the page's title by itsh1outside the navigation and the scroller as the shared page around it. They no longer use the removed.settings-page-titleand.settings-page-scroll. Behaviour is unchanged: every page is titled, the Workspace page follows the listed workspace, a page you turn to opens at its top, and search finds and lands on each moved option.pnpm check:affectedexits 0.
Evidence
These are from the smoke fixture on Linux under Xvfb, driven over CDP at 1280×840. The fixture is signed out, so Profile, Workspace, Coding agents, Integrations and Experimental show their signed-out lines. The ⌘ glyphs draw as boxes because the Linux font lacks them, on the base too.
| Light | Dark | |
|---|---|---|
| Voice | ![]() | ![]() |
| Keyboard shortcuts | ![]() | ![]() |
| About | ![]() | ![]() |
| Experimental (signed out) | ![]() | ![]() |
| Appearance | ![]() | ![]() |
| Search "font size" → result pressed, page landed on the row | ![]() | ![]() |
Not captured: the signed-in pages' bodies, which need a live account, and Experimental's empty state, which needs a signed-in account with no experiments.
Not verified on a Mac
- the drag strip above each page and the page's top fade under it
- scroll behaviour and the search landing's scroll position at real sizes, and zoom
- SF Pro rendering of the title
🤖 Generated with Claude Code
Summary by cubic
Migrates Settings' navigation and page frame onto @luke/ui's design system.
Every Settings page now uses the shared SettingsPage, which owns the page's inset, title, and section spacing; the desktop's own .settings, .settings-page-*, and drawnInSettingsPage gate are removed. The plan template's loading state and page list, search well, and group headings read the same role tokens their legacy names aliased. The branch carries main merged in, and its diff against main covers only D13's files.
- All pages now get a 40px page inset (32px previously), narrowing to 24px below 480px width; page titles sit 8px lower.
- A page turned to opens at its top, and a search result lands at the page's narrow inset.











