import QtQuick import Quickshell import Quickshell.Wayland import "." as M // Shared flyout popup window — slides down from the bar, dismisses on // click outside. Created on demand via Loader; animates in on creation, // animates out then emits dismissed() for the Loader to deactivate. PanelWindow { id: root default property alias content: contentCol.children required property var screen required property real anchorX property real panelWidth: 220 signal dismissed visible: true color: "transparent" WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.exclusiveZone: 0 WlrLayershell.namespace: "nova-popup" anchors.top: true anchors.left: true anchors.right: true anchors.bottom: true Component.onCompleted: showAnim.start() function dismiss() { showAnim.stop(); hideAnim.start(); } // Click outside → dismiss MouseArea { anchors.fill: parent onClicked: root.dismiss() } Item { id: panel x: Math.max(0, Math.min(Math.round(root.anchorX - contentCol.width / 2), root.width - contentCol.width)) y: 0 width: contentCol.width height: contentCol.height opacity: 0 // Eat clicks inside the panel MouseArea { anchors.fill: parent } Rectangle { anchors.fill: parent color: M.Theme.base01 opacity: Math.max(M.Theme.barOpacity, 0.85) topLeftRadius: 0 topRightRadius: 0 bottomLeftRadius: M.Theme.radius bottomRightRadius: M.Theme.radius } Column { id: contentCol width: root.panelWidth topPadding: 4 bottomPadding: 4 spacing: 2 } } ParallelAnimation { id: showAnim NumberAnimation { target: panel property: "opacity" from: 0 to: 1 duration: 150 easing.type: Easing.OutCubic } NumberAnimation { target: panel property: "y" from: -panel.height to: 0 duration: 200 easing.type: Easing.OutCubic } } ParallelAnimation { id: hideAnim NumberAnimation { target: panel property: "opacity" to: 0 duration: 150 easing.type: Easing.InCubic } NumberAnimation { target: panel property: "y" to: -panel.height duration: 150 easing.type: Easing.InCubic } onFinished: root.dismissed() } }