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 import "./Panes" as Panes PanelWindow { id: root anchors { top: true } property var font: {family: "0xProto Nerd Font"} implicitWidth: 1024 implicitHeight: 200 WlrLayershell.keyboardFocus: (up && !shortcut.pressed) ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None WlrLayershell.layer: WlrLayer.Overlay exclusionMode: ExclusionMode.Ignore color: "transparent" visible: false property bool up: false IpcHandler { target: "topbar" function open() { root.open() } function close() { root.close() } function toggle() { root.up ? close() : open() } } GlobalShortcut { id: shortcut name: "topbar" description: "Hold to peek, tap to toggle topbar" onPressed: { root.open() } onReleased: { if (!hover.hovered) root.close() } } function open() { root.visible = true background.exit.stop() if (!root.up) background.height = 0 root.up = true for (const child of background.children) { child.entry.start() } background.entry.start() } function close() { background.entry.stop() for (const child of background.children) { child.exit.start() } 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 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 Pane: Item { id: pane 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: pane property: "opacity" to: 1 duration: 300 easing.type: Easing.OutQuint } onStarted: fadeOut.stop() } property var fadeOut: NumberAnimation { target: pane property: "opacity" to: 0 duration: 300 onStarted: fadeIn.stop() easing.type: Easing.OutQuint } property var entry: SequentialAnimation { PauseAnimation {duration: 2} NumberAnimation { target: pane property: "anchors.topMargin" to: 0 duration: 300 easing.type: Easing.OutQuint onStarted: exit.stop() } } property var exit: NumberAnimation { target: pane property: "anchors.topMargin" to: -height duration: 300 easing.type: Easing.InQuint onStarted: entry.stop() } } Pane { opacity: 1; Panes.Status { }} Pane { Panes.Launcher { id: launcher onShowChanged: if (show) background.index = 1; else background.index = 0 }} Pane { Panes.Battery { }} property var entry: SequentialAnimation { PauseAnimation {duration: 2} NumberAnimation { target: background property: "height" to: background.children[background.index].height duration: 300 easing.type: Easing.OutQuint } } property var exit: NumberAnimation { target: background property: "height" to: 0 duration: 300 easing.type: Easing.InQuint onFinished: { root.visible = false root.up = false background.index = 0 launcher.clear() } } HoverHandler {id: hover} } }