nova-shell/modules/PopupPanel.qml
2026-04-12 18:44:27 +02:00

115 lines
2.7 KiB
QML

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()
}
}