import QtQuick import QtQuick.Controls import QtQuick.Effects import Quickshell import Quickshell.Hyprland import "../Color.js" as Colors Item { id: root property double animOffset: 0 property color boxColor: Colors.surface0 property double boxHeight: 28 property double boxRadius: 9 property double boxWidth: 100 readonly property double calculatedTopMargin: { if (root.exclusiveToScreen) { let baseMargin = hoverableWhenHidden == true ? 8 : -4; if (Hyprland.focusedMonitor != root.exclusiveMonitor || forceHidden == true) { return baseMargin - root.boxHeight - 5; } else { return visibleTopMargin; } } else { return visibleTopMargin; } } property Component defaultItem required property HyprlandMonitor exclusiveMonitor property bool exclusiveToScreen: false property bool forceHidden: false property alias hover: hoverHandler property bool hoverableWhenHidden: false property alias rect: container property alias stack: containerContent property alias tap: tapHandler property double visibleTopMargin: 0 implicitHeight: boxHeight implicitWidth: boxWidth Behavior on anchors.topMargin { animation: defaultCurve } Behavior on boxHeight { SpringAnimation { damping: 0.3 spring: 4 } } Behavior on boxRadius { SpringAnimation { damping: 0.3 spring: 4 } } Behavior on boxWidth { SpringAnimation { damping: 0.3 spring: 4 } } anchors { top: parent.top topMargin: calculatedTopMargin } NumberAnimation { id: defaultCurve duration: 200 + root.animOffset easing: Easing.InOutBack } HoverHandler { id: hoverHandler } TapHandler { id: tapHandler } RectangularShadow { anchors.fill: container blur: 30 color: Colors.mantle offset.x: 7 offset.y: 3 radius: container.radius spread: 10 } Rectangle { id: container anchors.fill: parent clip: true color: root.boxColor radius: root.boxRadius StackView { id: containerContent anchors.fill: parent replaceEnter: Transition { PropertyAnimation { duration: 100 from: 0 property: "opacity" to: 1 } PropertyAnimation { duration: 100 from: -5 property: "anchors.topMargin" to: 0 } } replaceExit: Transition { PropertyAnimation { duration: 100 from: 1 property: "opacity" to: 0 } } Component.onCompleted: containerContent.push(root.defaultItem) onCurrentItemChanged: { if (currentItem) { // Dynamically center the incoming child to the StackView currentItem.anchors.horizontalCenter = containerContent.horizontalCenter; currentItem.anchors.verticalCenter = containerContent.verticalCenter; } } } } }