Make Shell a category, the bar legible, and the dock a real dock

Desktop & Dock becomes Shell — Bar, Dock, Control Center, Tiling,
Workspaces — the home for everything Quickshell draws. The settings-
management cluster moves to System as Sync & Backup, Appearance's
Shell tab dissolves, and 24-hour time finally lives on Date & Time,
which always owned it.

The bar gets what it never had: a way to survive the wallpaper. A
second neutral text family (follow theme, or forced light or dark),
a one-layer shadow under every glyph, and a gradient scrim for
wallpapers nothing else survives — all off by default, pixel-identical
until asked. Widgets earn toggles (weather, media, clipboard, calendar
countdown), the vitals cluster stops leaving a dead pill behind, and
Control Center's sections learn to step aside.

The dock graduates from MVP: a context menu with window rows, pin,
unpin, quit and new-window; scroll an icon to cycle its windows; drag
to reorder on the dock itself; hover previews with one-shot captures;
and "Add App to Dock" in the launcher. Three real bugs died en route —
menus that slid away with the autohide, a readonly-property crash on
every menu open, and a drag that drifted half a slot per icon on side
docks. The pinned-apps editor in Settings becomes a drag strip.

166 contracts; the full suite is green except two live display and
switcher tests that cannot run behind a locked session — re-verified
on unlock.

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-24 04:28:20 -04:00
parent 4d7a194300
commit f8f5b25510
77 changed files with 2982 additions and 800 deletions
@@ -7,7 +7,7 @@ with Gabriel's go-ahead**, and failures get fixed then.
## The run
- `panama test` — the full suite (165 contracts as of the phase 3 contracts
- `panama test` — the full suite (**166** contracts as of the phase 4 Shell
wave; the top-level README's count line is set to match and is itself
checked by `setup/readme-contract`).
@@ -85,3 +85,106 @@ full-suite pass are deferred to the end-of-redesign sweep.
- `AppearancePage.qml`'s `tab` property defaults to `"background"` while its
own comment says Themes leads. Decide which is intended before the run;
nothing currently pins it either way.
## Phase 4 (Shell category) — append below
Spec: `2026-08-24-shell-category-redesign.md`. Desktop & Dock became **Shell**
(Bar · Dock · Control Center · Tiling · Workspaces), System gained **Sync &
Backup**, and the dock got its feature wave.
Unlike phases 2 and 3, the static and stubbed contracts in this wave **were
run** as they were written, and every one of them passed in isolation against
the tree. Two things are still deferred. The **live-harness halves** were not
run — the session was locked, and `dock-position-contract` opens a probe shell
while `settings-pages-contract` starts a settings harness, so those ran static-
only (`PANAMA_SETTINGS_STATIC_ONLY=1`) or not at all. And the **full-suite
pass**, the only thing that catches contention between harnesses, happens next
with Gabriel driving.
### New contracts (1)
| Contract | What it pins |
|---|---|
| `quickshell/bar-visibility-contract` | The bar's own neutral family: `barFg`/`barFgDim`/`barFgMuted` exist, each forced tone is anchored on one literal with both dims mixed off it, and the `theme` branch returns `root.fg`/`fgDim`/`fgMuted` **by identity** rather than a copied colour. All thirteen bar-text files bind to those tokens and none paints neutral text with the `fg` family (`Theme.alpha(Theme.fg, …)` hover and separator fills are allowed; semantic tones were never in scope). `Bar.qml`'s scrim reads `visible: Settings.barBackdrop`, its shadow reads `layer.enabled: Settings.barTextShadow` over exactly one `MultiEffect` layer, and neither may be a literal `true` — both shipped hardcoded during the build, which is the regression this exists for. Plus the four widget gates ANDed with their state conditions, `VitalsWidget`'s whole-pill `visible`, `exclusiveZone: Theme.barHeight` still literal, no animation anywhere in `Bar.qml`, and the two right-click jumps landing on `bar`. |
Mutation-checked while writing: hardcoding the shadow, returning a literal from
the `theme` branch, putting one widget back on `Theme.fg`, deleting the vitals
pill's own `visible`, and adding a `Behavior` to `Bar.qml` each fail it with a
message naming the actual problem.
### Updated contracts (5)
| Contract | What it now pins |
|---|---|
| `quickshell/dock-position-contract` | `DockPinsEditor``DockPinsStrip`: `preventStealing` moved to the strip, the retired ↑/↓ buttons replaced by the strip's own keyboard path (Left/Right move, Delete unpins), and a new section for the **live** dock's drag-to-reorder — commits once on release, and measures a slot from a real icon rather than a constant, because a `DockItem` is taller than it is wide and a constant is wrong on one orientation. |
| `quickshell/settings-jump-contract` | `DockContextMenu`'s "Dock settings" now opens `dock`, not the retired `desktop`. |
| `quickshell/settings-pages-contract` | Six new pages added to the page sweep (Bar, Dock, ControlCenter, Tiling, Workspaces, Sync); `vitalsIntervalMs` and the graphics ChoiceGrid now required on `BarPage` rather than `AppearancePage`, since the vitals are bar content and not surface appearance. |
| `setup/projects-contract` | The saved-projects list moved from the deleted `DesktopPage.qml` to `WorkspacesPage.qml`. |
| `quickshell/panama-commands-contract` | The launcher's new `dock-add-app``panama-action dock-pin` command. |
### Verified against the new tree, no edit needed
Every one of these was **run** and passed after the phase-4 changes landed:
- `quickshell/settings-search-contract` — the new `bar`/`controlCenter`/
`datetime` groups and the re-pointed `dock`/`multitasking`/`edges`/`master`/
`notices`/`focus` routes are covered by the schema-label sweep already.
- `quickshell/settings-ownership-contract` — the six intentional mirrors and the
eleven README literals survived the rewrite; no new mirror was introduced.
- `quickshell/settings-nav-contract` — 14 categories, 38 leaves, 2 retired ids
(`home-phone`, `desktop`).
- `quickshell/manual-contract`, `gnome-handoff-contract` (15 handoffs against
38 pages), `control-center-contract`, `welcome-contract`,
`accent-controls-contract`, `theme-catalog-contract`,
`desktop-style-contract` — checked, nothing stale.
`welcome-contract` passed in isolation again here, which does not settle the
phase-3 flake above: that failure only appeared under a storming full-suite run.
### Docs updated in the same wave
- `docs/settings.md` and the 37 `settings-*` launcher commands — regenerated by
`panama-settings-docs` and `panama-settings-commands`; both `--check` modes
clean and both generators verified idempotent. `settings-desktop` is deleted,
`settings-bar`/`-dock`/`-control-center`/`-tiling`/`-workspaces`/`-sync` are
new, and `dock-add-app` joins them.
- `modules/settings/README.md` — new **Shell** section (the five tabs, the bar
token design and why it exists, the pins strip and the live dock's gestures,
the Control Center rule that only real sections get toggles) and a new
**System Sync & Backup** section. Appearance corrected from six tabs to
five, saying where the Shell tab went.
- `manual/05-making-it-yours.md` — new **Shell** chapter section (bar
legibility, widget switches, why `use24Hour` is not there, the pins strip,
the dock's drag/right-click/scroll/preview gestures, **Add App to Dock**,
Control Center sections) plus **Carrying settings between machines**.
`manual/03-windows-and-workspaces.md` — the multi-display workspace switch
now points at Displays, which is where it actually is, instead of the deleted
Desktop & Dock page.
- Top-level `README.md` — contract count 165 → 166, recounted the way
`panama test` collects (executable, or `*_test.py`, excluding fixtures and
`__pycache__`).
### Still open before the run
- Four contracts in the working tree changed for reasons **outside** this
phase and are not accounted for above: `declared-assets-contract` (`pkill`,
from the video wallpaper work), `declared-dependencies-contract` (`cmp`
diffutils), `panama-doctor-contract` (29 → 30 check ids), and
`lock-screen-helper-contract` / `video-wallpaper-contract` (theme-derived
literals and the mpv IPC key quoting). Confirm each belongs to a wave that
intended it before the suite runs.
- `tests/setup/update-command-contract` is untracked and belongs to the
separate `panama update` design, not to this redesign. It **is** inside the
166.
- `quickshell/dock-position-contract` has never had its **live** half run since
the strip landed: it opens a probe shell, and this wave ran under a locked
session. Its static half is what was verified. Run it first in the sweep.
- `quickshell/settings-pages-contract` passed static-only for the same reason.
Its compositor-integration half — the settings harness, its IPC, and the
page-open checks — is unverified against the six new pages.
- `Bar.qml` has one stray indentation glitch at its first `Row` (line 105).
Cosmetic, untouched here because the file is not this wave's to reformat.
- 2026-08-24 full-suite run: 166 contracts, all green except `displays-contract`
and `switcher-contract`, which are live interactive tests that cannot run
behind hyprlock (both passed in the same day's unlocked run; neither
subsystem changed in phase 4). Re-verify after unlock.
@@ -0,0 +1,98 @@
# Shell category — Bar · Dock · Control Center · Tiling · Workspaces
Approved 2026-08-24 (interactive mock). Desktop & Dock becomes **Shell**: the home for
everything Quickshell draws. Five tabs, three of them new surfaces. The settings-
management cluster leaves for System; Appearance's Shell tab dissolves into the Bar
tab; the dock's feature upgrade (drag-reorder on the dock, context menu, previews,
scroll cycling, launcher pin command) lands separately once the research report is in.
## Routing
Category id `shell`, label **Shell**, keeping the old icon. Leafs: `bar`, `dock`,
`control-center`, `tiling`, `workspaces` — five new pages; `DesktopPage.qml` dies.
Retired: `desktop``bar` (first tab). `DockContextMenu`'s "Dock settings" deep-links
to `dock`. System gains leaf `sync` ("Sync & Backup"), ten tabs total.
## Bar (the new surface)
**Visibility.** New schema group `bar`:
- `barTextTone` enum `theme|light|dark` (def `theme`) — drives new Theme tokens
`barFg`/`barFgDim`/`barFgMuted` (theme ⇒ today's fg family; light ⇒ near-white with
derived dims; dark ⇒ near-black likewise). Bar widgets rebind their ~26 neutral
text/glyph bindings to the bar tokens — semantic tones (warn/danger/accent/ok) stay.
- `barTextShadow` bool (def false) — one `layer.effect` MultiEffect shadow over the
whole bar content; one change covers every widget and icon. Event-driven repaints
only; the bar already repaints once a second for the clock.
- `barBackdrop` bool (def false) — a top-down gradient scrim Rectangle behind the
content rows.
**Widgets card.** New bools (group `bar`, all def true): `showWeatherWidget`,
`showMediaWidget`, `showClipboardButton`, `showCalendarCountdown` — each ANDed with
the widget's existing state condition. Moved here: `showCpu/showMemory/showGpu`,
`showBattery`, `showBatteryPercent`, `showAgentUsage`. Fix in passing: VitalsWidget
renders no pill at all when all three fields are off (today an empty dead pill stays).
State-driven indicators (health, activity, focus, wallpaper, calendar-within-window)
stay automatic.
**Clock card.** `showSeconds`, `showWeekday` (group `clock`, now routing to `bar`).
`use24Hour` moves to a new group `datetime` routing to the Date & Time page, which
gains the toggle — it drives the date menu, notifications, and the lock screen, and
was never just the bar's.
**Vitals card.** `vitalsIntervalMs` + the graphics-device ChoiceGrid, moved from
Appearance.
## Dock
`DockPage.qml`: the Dock behavior card (position, screens, autohide, delays, icon
size — unchanged rows), then **Pinned applications** rebuilt as `DockPinsStrip.qml`:
a horizontal strip of app icons (real icons, the dock's own resolution), drag to
reorder, hover-× to unpin, the existing `DockAppPicker` search beneath. The
16-full-rows editor (`DockPinsEditor`) retires; its drag mechanics inform the strip.
The dock-position contract's `preventStealing` pin moves to the strip.
## Control Center
`ControlCenterPage.qml` — the panel's first settings surface. New schema group
`controlCenter`: one show/hide bool per real section of `QuickSettingsPanel`
(verified against the panel's actual structure at build time; the mock showed Focus,
Home, Phone, Media as candidates — only sections that exist get toggles). Plus an
Accessories handoff row to Home My Home.
## Tiling
`TilingPage.qml`: Window layout (+ the Appearance Windows handoff), Master & stack
(visible when master), Window edges, Hyprland notices — all rows moved unchanged.
## Workspaces
`WorkspacesPage.qml`: Workspaces & focus toggles, Focus session length, Projects —
moved unchanged.
## System Sync & Backup
`SyncPage.qml` (leaf `sync`): "Carry settings to another machine" (SettingsSync),
"Settings backups" (SettingsBackup — retitled so it stops colliding with btrfs
Snapshots one tab over), "Reset". The `Restore defaults` search entry re-points here.
## Appearance shrinks
The `shell` tab and its two cards leave `AppearancePage`; five tabs remain.
## Blast radius
- `SettingsSearch.groupPages`: dock/multitasking/edges/master/notices → their new
leafs; `focus``workspaces`; `vitals`+`clock``bar`; new `datetime``datetime`;
new `bar`/`controlCenter` groups. extraEntries: "Restore defaults" → `sync`; new
entries for bar visibility, dock pins, control center.
- Contracts updated in-phase (tests are runnable this pass): settings-jump
(DockContextMenu → `dock`), projects-contract (DesktopPage greps → WorkspacesPage),
dock-position-contract (strip), desktop-style/lock-screen-settings (Appearance card
lists), search fixed cases, ownership groupPages cross-checks, agent-usage
(unchanged gating), plus a new bar-visibility contract.
- Generators re-run; README/manual updated.
## Deferred (dock feature wave, post-research)
Drag-reorder on the live dock, right-click unpin/window actions, window previews,
scroll cycling, the launcher "Add app to dock" command.