import Quickshell import Quickshell.Io import Quickshell.Hyprland import Quickshell.Wayland import QtQuick import QtQuick.Controls import QtQuick.Effects import QtQuick.Shapes import "." as Shell PanelWindow { id: root anchors { top: true } implicitWidth: 1024 implicitHeight: 200 WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand WlrLayershell.layer: WlrLayer.Overlay exclusionMode: ExclusionMode.Ignore color: "transparent" property bool up: false IpcHandler { target: "topbar" function open() { root.open() } function close() { root.close() } function toggle() { root.up ? close() : open() } } function open() { background.index = 0 background.entry.start() } function close() { background.exit.start() } Shell.BarShape { id: background anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top color: "#222222" radius: 16 width: children[0].width + radius*2 height: children[0].height component DefaultTransition: Behavior { enabled: root.up NumberAnimation { duration: 500 easing.type: Easing.OutQuint } } DefaultTransition on width { } DefaultTransition on height { } property int index: 0 HoverHandler { onHoveredChanged: if (!hovered) { root.close() }} onIndexChanged: { width = children[index].width + radius*2 height = children[index].height for (const [i, child] of children.entries()) { if (i === index) { if (root.up) child.fadeIn.start() else child.opacity = 1 } else { if (root.up) child.fadeOut.start() else child.opacity = 0 } } } component Display: Item { id: display anchors { top: parent.top horizontalCenter: parent.horizontalCenter } width: children[0].width height: children[0].height opacity: 0 property var fadeIn: SequentialAnimation { PauseAnimation {duration: 200} NumberAnimation { target: display property: "opacity" to: 1 duration: 300 easing.type: Easing.OutQuint } onStarted: fadeOut.stop() } property var fadeOut: NumberAnimation { target: display property: "opacity" to: 0 duration: 300 onStarted: fadeIn.stop() easing.type: Easing.OutQuint } property var entry: NumberAnimation { target: display property: "anchors.topMargin" to: 0 duration: 300 easing.type: Easing.OutQuint onStarted: exit.stop() } property var exit: NumberAnimation { target: display property: "anchors.topMargin" to: -height duration: 300 easing.type: Easing.InQuint onStarted: entry.stop() } } Display { opacity: 1; Shell.Status { anchors { top: parent.top horizontalCenter: parent.horizontalCenter } } } Display { Shell.Launcher { onShowChanged: if (show) background.index = 1; else background.index = 0 anchors { top: parent.top horizontalCenter: parent.horizontalCenter } } } property var entry: NumberAnimation { target: background property: "height" to: background.children[background.index].height duration: 300 easing.type: Easing.OutQuint onStarted: { root.implicitHeight = 200 background.exit.stop() root.up = true for (const child of background.children) { child.entry.start() } } } property var exit: NumberAnimation { target: background property: "height" to: 0 duration: 300 easing.type: Easing.InQuint onStarted: { background.entry.stop() for (const child of background.children) { child.exit.start() } } onFinished: { root.implicitHeight = 1 root.up = false background.index = 0 } } } HoverHandler { onHoveredChanged: if (hovered) { root.open() }} }