feat(quickshell): popouts grow out of the frame

Hover panels used to float a gap away from their trigger as free-standing
cards. They are now part of the hull: flush against the frame edge they
open from, painted in the hull colour, joined to it through concave
fillets, with the porthole rim carried round their open side, and they
slide out from behind the frame instead of fading and scaling in.

Popout places itself rather than relying on the compositor's slide
adjustment. A panel is centred on its trigger and, if that lands it near
one of the opening's corners, docked into the corner — attached to the
bar and the rail at once — so it never leaves a thin strip of opening
between itself and the rail. The calendar, network and audio panels dock
top-right; notifications dock bottom-right.

PopoutSurface leaves fill, border and corner ticks to the hull when it is
inside a Popout, and keeps them in the launcher and the ask panel. Its
attached fill opacity is 0 rather than a transparent colour, because
P5Panel re-applies fillOpacity to the colour and turned "transparent"
into 97% black.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
nvrlandClaude Opus 5.5 committed 2026-10-04 20:34:17 +02:00
1 parent ecc7d2884c
commit 196abc2311
3 files changed
+266 -92

No files matched your search

+17 -1
View File
@@ -42,7 +42,7 @@ cost 4.4% of the height on top of what the bar already takes.
- **bar** — identity and workspaces on the left; the focused window, the
player, the CPU/MEM/GPU readout and the clock on the right.
- **rail** — network, bluetooth, audio, mic, backlight, battery, tray,
notifications, power. Popouts open leftward, into the screen.
notifications, power. Popouts grow leftward out of it, into the screen.
Modules are divided by hairlines. `BarPill` is chromeless by default — a module
is *content inside* the hull, not a surface of its own — and marks hover with
@@ -72,6 +72,22 @@ assets/ halftone and stripe tiles, generated with ImageMagick
callers set implicit sizes from their own layout (`row.implicitWidth +
contentPad * 2`), which keeps the shape maths out of binding loops.
## Popouts
Hover panels (`components/Popout.qml`) are part of the hull, not cards
floating near their trigger. Each one sits flush against the frame edge it
opens from, is painted in the hull colour, joins the frame through concave
fillets, carries the rim round its open side, and slides out from behind the
frame. `PopoutSurface` notices it is inside a `Popout` and leaves the fill and
the frame to the hull; in the launcher and the ask panel it is still a
free-standing panel with corner ticks.
Placement is explicit: centred on the trigger, then — if that would land the
panel within `dockReach` of one of the opening's corners — docked into the
corner instead, attached to the bar and the rail at once (`dock` is `top`,
`right`, `topRight` or `bottomRight`). Without docking, a panel near the rail
left a thin strip of opening between itself and the rail.
## Dashboard
`dashboard/Dashboard.qml` is a drawer that slides down out of the underside of