quickshell: flush dropdowns live anchored to the column — grow down-left, shrink back into it

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-06-12 09:44:19 +01:00
parent ad2cbd0eaa
commit 724cdded4c

View file

@ -1299,13 +1299,11 @@ in
property real openH: bar.activeDropdown ? tH : 0 property real openH: bar.activeDropdown ? tH : 0
property bool snap: false property bool snap: false
readonly property real stubW: 32 readonly property real stubW: 32
// Melt toward the frame column whenever a flush dropdown // Merged whenever the (latched) target is a flush dropdown
// is the active target the geometric melt runs during // and the panel is on screen flush panels are born,
// the approach and un-melts during departure. (A previous // live and close merged; the melt only animates for
// contact-detection compare against animated float // morphs between flush and centered dropdowns.
// geometry proved unreliable on scaled displays.)
readonly property bool mergedRight: visible && flushRight readonly property bool mergedRight: visible && flushRight
&& bar.activeDropdown !== null
// Grow-from / shrink-to the widget that owns the dropdown: // Grow-from / shrink-to the widget that owns the dropdown:
// the panel opens as a small stub on the button and // the panel opens as a small stub on the button and
@ -1314,14 +1312,19 @@ in
function stubX(dd) { function stubX(dd) {
return Math.round(Math.min(bar.width - Theme.frameWidth - stubW, Math.max(Theme.frameWidth, dd.dropdownX - stubW / 2))); return Math.round(Math.min(bar.width - Theme.frameWidth - stubW, Math.max(Theme.frameWidth, dd.dropdownX - stubW / 2)));
} }
// Flush dropdowns keep their right edge welded to the
// frame column: they grow down-and-left from a stub
// parked at the column and shrink back into it. (x and
// width share one animation curve, so x+width the right
// edge is constant mid-flight.)
function seedFromButton(dd) { function seedFromButton(dd) {
snap = true; snap = true;
tX = stubX(dd); tX = dd.alignRight ? bar.width - Theme.frameWidth - stubW : stubX(dd);
tW = stubW; tW = stubW;
snap = false; snap = false;
} }
function shrinkToButton(dd) { function shrinkToButton(dd) {
tX = stubX(dd); tX = dd.alignRight ? bar.width - Theme.frameWidth - stubW : stubX(dd);
tW = stubW; tW = stubW;
} }
@ -1374,6 +1377,10 @@ in
// flare one shape the whole way. // flare one shape the whole way.
property real mergeP: mergedRight ? 1 : 0 property real mergeP: mergedRight ? 1 : 0
Behavior on mergeP { Behavior on mergeP {
// Only animate while the panel is on screen flush
// panels opening from closed are born merged, no
// visible melt-in at birth.
enabled: chrome.height > 0.5
NumberAnimation { duration: 150; easing.type: Easing.OutCubic } NumberAnimation { duration: 150; easing.type: Easing.OutCubic }
} }