feat(quickshell): give the prompt its own panel, ESC handling and placement

PolkitPanel replaces BarPanel as the dialog's chrome. Deliberately not a
subclass or a fork: most of BarPanel is density machinery — summary slot,
animated height, state pair, transitions — that a modal never uses, and
inheriting it would tie the dialog's look to a component whose real job is the
rail, so every restyle here would have to be justified against the panels up
there. It keeps the shell's silhouette (cut corners with detached accent caps,
the accent rules, the header strip) and drops the rail's tick decoration.

ESC closes the rail. The bar had no keyboard focus at all, so this adds it,
gated by the shell rather than left to the compositor to arbitrate between two
exclusive surfaces — that resolves by stacking and would invert silently the
day the layers change:

    grabsKeyboard: shell.expanded && !polkit.prompting

so ESC dismisses the prompt while one is open and closes the rail afterwards.
Verified by instrumenting the handoff: expanded -> true, prompt open -> false,
prompt dismissed -> true, collapsed -> false. Note the rail now takes EXCLUSIVE
keyboard focus while expanded, which is the cost of answering a keypress the
user has not aimed at anything.

The dialog sits a third of the way down rather than centred, panel centre on
the third so it grows symmetrically as the message wraps, floored at a margin
so a tall prompt on a short output cannot be pushed off the top.

Also carries the backdrop tuning: dim 0.75 -> 0.65, gridOpacity 0.15 -> 0.10,
crossOpacity 0.45 -> 0.15, now that the scrim is used by the prompt as well as
the rail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GAq2kKCLazZmrKvkd3akud
This commit is contained in:
2026-09-01 23:38:23 +02:00
co-authored by Claude Opus 5
parent 27b924f5e9
commit b3c3cc38f0
6 changed files with 273 additions and 22 deletions
@@ -189,6 +189,16 @@ Scope {
visible: shell.targetScreen !== null
expanded: shell.expanded
wlrLayer: shell.barLayer
// ESC closes the rail — but only when it is the innermost thing open.
// While a prompt is up the rail gives up the keyboard so ESC dismisses
// the DIALOG; the prompt closing hands it back, and the next ESC closes
// the rail. Withheld rather than left to the compositor to arbitrate
// between two exclusive surfaces, which would decide by stacking and
// silently swap the order the day the layers change.
grabsKeyboard: shell.expanded && !polkit.prompting
onDismissed: shell.expanded = false
}
// Polkit authentication agent. It registers for this logind session on