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 committed 2026-08-24 04:28:20 -04:00
1 parent 4d7a194300
commit f8f5b25510
77 files changed
+2982 -800

No files matched your search

@@ -80,12 +80,15 @@ Settings because Fedora's system services own those areas.
## Appearance
Six tabs, in the order the questions are actually asked: **Themes**, **Theme
editor**, **Background**, **Typography**, **Windows**, **Shell**. Themes leads
because light and dark is the control reached most often, and it used to be the
third section down, under a wallpaper grid and the whole lock screen. The old
`theme` section id still resolves to it, so deep links and IPC calls keep
working.
Five tabs, in the order the questions are actually asked: **Themes**, **Theme
editor**, **Background**, **Typography**, **Windows**. Themes leads because
light and dark is the control reached most often, and it used to be the third
section down, under a wallpaper grid and the whole lock screen. The old `theme`
section id still resolves to it, so deep links and IPC calls keep working.
The sixth tab, **Shell**, is gone: its two cards moved to **Shell › Bar**, which
is where somebody who wants to change the bar now looks. Appearance answers what
the desktop looks like; Shell answers what the desktop *is*.
### Themes
@@ -145,6 +148,109 @@ and Panama's own Settings titlebar shows one button. `panamaTitlebar` turns
that bar off entirely, leaving the window pure Hyprland: Super+Q closes,
Super+drag moves, Escape still works.
## Shell
Everything Quickshell itself draws, in five tabs: **Bar**, **Dock**, **Control
Center**, **Tiling**, **Workspaces**. The category used to be **Desktop & Dock**,
a single page that held the dock alongside window layout, workspaces, and the
settings-management cluster — three unrelated subjects and a filing cabinet. Its
`desktop` id is retired to `bar`, so old deep links land on the first tab.
The split is by *surface*. If you can point at it on screen, it has a tab.
### Bar
The first settings surface the bar has ever had. Three cards.
**Visibility** exists because the bar is the one thing the shell draws that has
no ground of its own — it floats on the wallpaper, which the theme has never
seen. So a palette that is correct everywhere else can still be unreadable
exactly where the clock is. `barTextTone` (`theme`/`light`/`dark`) drives a
second neutral family in `Theme.qml` — `barFg`, `barFgDim`, `barFgMuted` — that
thirteen bar widgets bind to instead of `fg`/`fgDim`/`fgMuted`. Left on `theme`
the family *is* the fg family by identity, so nothing changes for anyone who
never asks, and a custom palette still reaches the bar. Semantic tones (warn,
danger, accent, ok) never became bar tones: a battery at 4% is red whatever the
neutrals were forced to.
`barTextShadow` and `barBackdrop` are the two escape hatches for a wallpaper no
tone wins against. The shadow is **one** `layer.effect` MultiEffect over the
whole of `Bar.qml`'s content rather than one per widget, so a widget added
tomorrow picks it up without opting in; the backdrop is a static top-down
gradient Rectangle behind the content rows. Both default off and both are read
from the preference — during the build they briefly landed as literal `true`,
which forced a dark band and an extra compositing layer on everyone.
`tests/quickshell/bar-visibility-contract` pins both bindings for that reason,
along with every widget's use of the bar tones.
**Widgets** is one toggle per thing that earns a place: weather, media,
clipboard, calendar countdown, the three vitals readouts, battery, agent usage.
Each toggle is **ANDed** with the widget's own state condition rather than
replacing it, so switching one on never conjures a pill with nothing in it.
State-driven indicators — health, activity, focus, video wallpaper — get no
toggle: they appear when they have something to say and leave when they are
done. `VitalsWidget` answers for its own pill as well as its three fields,
because an invisible child still occupies its Row and gating the fields alone
left a padded, empty pill in the bar.
**Clock** keeps `showSeconds` and `showWeekday`. `use24Hour` is *not* here: it
drives the date menu, notification timestamps, and the lock screen too, so it
moved to group `datetime` and lives on **System › Date & Time**. The card says
so rather than leaving its absence looking like an oversight.
Right-clicking the vitals or agent-usage pill opens this page.
### Dock
Behavior — position, screens, autohide, reveal and hide delays, icon size —
unchanged. **Pinned applications** is now `DockPinsStrip.qml`: the dock's own
row of icons, resolved exactly the way the dock resolves them, drag to reorder,
hover for the unpin ×, `DockAppPicker` search underneath. It replaces a sixteen-
row list of names, which was honest but was not the thing being edited — the
order of a horizontal row of icons was being decided in a vertical column of
text.
Two details make the drag safe: `preventStealing` on the grabbing MouseArea, or
the page's Flickable claims the gesture and the icon never moves; and the order
is held in the strip while the drag runs and written **once** on release, rather
than rewriting `settings.json` a dozen times for one gesture. Every icon is also
a tab stop — Left and Right move it, Delete unpins it — because a drag is not
reachable from the keyboard.
The live dock gained the matching gestures: drag to reorder on the dock itself,
a right-click menu (window rows, pin, unpin, quit, new window, and a **Dock
settings** entry that deep-links here), scroll an icon to cycle its windows, and
hover previews from `DockPreviews.qml`. `DockPickOverlay.qml` plus the `dock`
IPC target back the launcher's **Add App to Dock** command, so pinning never
requires opening Settings at all.
### Control Center
The quick settings panel's first settings surface. **Sections** is one
`ccShow*` bool per real section of `QuickSettingsPanel` — Focus, Home, Phone —
and only for sections that actually exist; a toggle for a section the panel does
not draw is a control that writes a preference nothing reads. Turning one off
hides it from the panel and stops nothing: the page behind it still works.
**Accessories** is a labeled handoff to Home › My Home rather than a second copy
of the shelf editor.
### Tiling and Workspaces
Rows moved unchanged. Tiling holds window layout (with the handoff to Appearance
› Windows for gaps, corners, and effects), master and stack, window edges, and
the Hyprland notices. Workspaces holds the workspace and focus toggles, focus
session length, and Projects.
## System › Sync & Backup
`SyncPage.qml`, the tenth tab of System: **Carry settings to another machine**
(`SettingsSync`), **Settings backups** (`SettingsBackup`), and **Reset**. It was
the settings-management cluster on the old Desktop page, which is the one thing
on that page that was never a surface. Backups is titled that way deliberately
so it stops colliding with the btrfs **Snapshots** tab one along — the two mean
different things and used to share a word. The search index's **Restore
defaults** entry points here.
## Adding a setting
One schema entry. That is the whole job.