Files
monoshell/TopBar.qml
2026-02-26 16:18:06 -08:00

186 lines
5.4 KiB
QML

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: 400
WlrLayershell.keyboardFocus: (up && !background.exit.running && !shortcut.pressed && background.index <= 1) ? 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: {
background.index = 0
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 {} }
Pane { Panes.NotificationCenter {} }
Pane { Panes.Notifications {} }
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}
}
}