The sidebar was a flat scan of thirty-one rows; now it reads like a settings app. Multi-subject categories (Input, Network & Sharing, Applications, Users & Accounts, Privacy & Security, System) carry an Appearance-style tab strip above the page, drawn by the shell so the leaf pages themselves are untouched. The taxonomy lives in one new file, services/SettingsRoutes.qml; the sidebar, the strip, route validation, search breadcrumbs, and both generators derive from it. ShellState.settingsPage still holds leaf ids, so every deep link, IPC call, and search result keeps working — and now lands on the exact tab. Dictation moves out of Sound onto its own page under Input, with a handoff back to Sound for the microphone. The strip scrolls when System's nine tabs outgrow a tiled window. All 161 contracts pass. Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
4.1 KiB
4.1 KiB
Settings navigation redesign — 31 flat pages become 15 categories
Approved 2026-08-23. The sidebar's 31 entries collapse into 15 categories. Multi-subject categories render an Appearance-style tab strip above the page; single-subject categories render no strip. Every old page id keeps working forever.
The taxonomy
| Category (sidebar) | Tabs (leaf page ids) |
|---|---|
| Home | — (home) |
| Appearance | — (appearance, keeps its internal tabs) |
| Desktop & Dock | — (desktop) |
| Displays | — (displays) |
| Sound | — (sound, Dictation card moves out) |
| Notifications & Focus | — (notifications) |
| Input | Keyboard (shortcuts), Mouse & Touchpad (mouse), Dictation (dictation, new) |
| Network & Sharing | Connections (connectivity), Firewall (firewall), Sharing (sharing), Printers (printers) |
| Home & Phone | — (home-phone) |
| Applications | Applications (applications), Gaming (gaming), Screen Intelligence (screen-intelligence) |
| Users & Accounts | Users (users), Online Accounts (accounts) |
| Privacy & Security | Privacy (privacy), SSH Keys (ssh-keys) |
| Power & Lock | — (power) |
| Accessibility | — (accessibility) |
| System | About (about), Software Update (updates), System Health (services), Storage (storage), Snapshots (snapshots), Containers (containers), Date & Time (datetime), Region & Language (region), Manual (manual) |
Architecture
ShellState.settingsPage keeps holding the leaf id, exactly as today. The page loader's
switch, the ownership contracts, HomePage's direct jumps, and every external caller are
untouched by the grouping itself. What changes:
services/SettingsRoutes.qml(new singleton) — the one source of truth for the taxonomy:categories(page, label, icon, tabs),resolve(id)(category id → first available leaf; leaf → itself; unknown → home),categoryOf(leaf),tabsFor(leaf)(availability-filtered),breadcrumb(leaf),pageAvailable(leaf)(the podman/snapper gating, moved from the sidebar).SettingsSidebar.qml— destinations come fromSettingsRoutes.categories; a row highlights when it is the category owning the current leaf; clicking requests the category id andShellStateresolves it.ShellState.showSettings— the literal allow-list becomesSettingsRoutes.resolve().SettingsShell.qml— renders aSettingsTabsstrip between the titlebar and the page loader whenever the current leaf's category has more than one available tab. Tab click is justopenSettings(leafId). Adds thedictationcase.SettingsTabs.qml— the strip becomes horizontally scrollable when it overflows (System has nine tabs; the window tiles down to 900px).SoundPage.qml/DictationPage.qml(new) — the Dictation card moves to its own page under Input, with a labeled handoff noting the microphone is chosen in Sound.SettingsSearch.qml— dictationextraEntriesre-route todictation; the search result subtitle becomes theSettingsRoutesbreadcrumb ("System › Storage"). Because results carry leaf ids, search now lands on the exact tab with no further work.
Blast radius owned by this change
scripts/panama-settings-commandsregex-parses the sidebar's destinations array; it moves to parsingSettingsRoutes.qmland regenerates the Vicinae commands (one per leaf;homestill skipped;dictationgained).scripts/panama-settings-docschecked the same way.- Test contracts updated in the same change, not after:
settings-nav-contract,settings-jump-contract,search-routing-contract,gnome-handoff-contract,manual-contract,sound-page-contract, plus any contract found grepping page ids. modules/settings/README.mdgains the navigation model; manual chapter05-making-it-yours.mdupdated where it describes the sidebar.
Non-goals
- No per-tab deep links into Appearance's internal tabs from search (unchanged today).
- No persistence of last-selected tab per category (Appearance already resets; same rule).
- No renaming of leaf ids, files, or schema groups.