From 42ec379a87a67b85e3eebb0c77f3d8e16375ec0d Mon Sep 17 00:00:00 2001 From: Damocles Date: Sun, 12 Apr 2026 16:03:17 +0200 Subject: [PATCH] prettier osd --- modules/Osd.qml | 126 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 87 insertions(+), 39 deletions(-) diff --git a/modules/Osd.qml b/modules/Osd.qml index eb0cc1c..9e7a47a 100644 --- a/modules/Osd.qml +++ b/modules/Osd.qml @@ -3,72 +3,120 @@ import Quickshell import Quickshell.Wayland import "." as M +// OSD overlay — slides out from the bar, centered on screen. +// Attached to the bar (square top corners, flush below it). PanelWindow { id: root required property var screen - visible: M.OsdState.visible + // Stay visible while animating out + visible: M.OsdState.visible || hideAnim.running color: "transparent" WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.exclusiveZone: 0 WlrLayershell.namespace: "nova-osd" + mask: Region {} - anchors.bottom: true + anchors.top: true anchors.left: true - margins.bottom: Math.round(screen.height / 3) + margins.top: 0 margins.left: Math.round((screen.width - implicitWidth) / 2) implicitWidth: 200 implicitHeight: 48 - Rectangle { - anchors.fill: parent - color: M.Theme.base00 - opacity: Math.max(M.Theme.barOpacity, 0.85) - radius: M.Theme.radius + // Slide + fade animation state + property bool _shown: M.OsdState.visible + on_ShownChanged: { + if (_shown) { + hideAnim.stop(); + showAnim.start(); + } else { + showAnim.stop(); + hideAnim.start(); + } } - Row { - anchors.centerIn: parent - spacing: 10 + ParallelAnimation { + id: showAnim + NumberAnimation { target: content; property: "opacity"; to: 1; duration: 150; easing.type: Easing.OutCubic } + NumberAnimation { target: content; property: "y"; to: 0; duration: 200; easing.type: Easing.OutCubic } + } - Text { - text: M.OsdState.icon - color: M.Theme.base05 - font.pixelSize: M.Theme.fontSize + 4 - font.family: M.Theme.iconFontFamily - anchors.verticalCenter: parent.verticalCenter + ParallelAnimation { + id: hideAnim + NumberAnimation { target: content; property: "opacity"; to: 0; duration: 250; easing.type: Easing.InCubic } + NumberAnimation { target: content; property: "y"; to: -content.height; duration: 250; easing.type: Easing.InCubic } + } + + Item { + id: content + anchors.left: parent.left + anchors.right: parent.right + height: root.implicitHeight + opacity: 0 + y: -height + + // Background — flush with bar above + Rectangle { + anchors.fill: parent + color: M.Theme.base00 + opacity: Math.max(M.Theme.barOpacity, 0.85) + topLeftRadius: 0 + topRightRadius: 0 + bottomLeftRadius: M.Theme.radius + bottomRightRadius: M.Theme.radius } - Item { - width: 120 - height: 6 - anchors.verticalCenter: parent.verticalCenter + Row { + anchors.centerIn: parent + spacing: 10 - Rectangle { - anchors.fill: parent - color: M.Theme.base02 - radius: 3 - } - - Rectangle { - width: parent.width * Math.min(1, Math.max(0, M.OsdState.value)) - height: parent.height + // Icon + Text { + text: M.OsdState.icon color: M.Theme.base0D - radius: 3 + font.pixelSize: M.Theme.fontSize + 6 + font.family: M.Theme.iconFontFamily + anchors.verticalCenter: parent.verticalCenter } - } - Text { - text: Math.round(M.OsdState.value * 100) + "%" - color: M.Theme.base05 - font.pixelSize: M.Theme.fontSize - font.family: M.Theme.fontFamily - anchors.verticalCenter: parent.verticalCenter - width: 30 + // Progress bar + Item { + width: 120 + height: 6 + anchors.verticalCenter: parent.verticalCenter + + Rectangle { + anchors.fill: parent + color: M.Theme.base02 + radius: 3 + } + + Rectangle { + width: parent.width * Math.min(1, Math.max(0, M.OsdState.value)) + height: parent.height + color: M.Theme.base0D + radius: 3 + + Behavior on width { + NumberAnimation { duration: 120; easing.type: Easing.OutCubic } + } + } + } + + // Percentage + Text { + text: Math.round(M.OsdState.value * 100) + "%" + color: M.Theme.base05 + font.pixelSize: M.Theme.fontSize + font.family: M.Theme.fontFamily + anchors.verticalCenter: parent.verticalCenter + width: 32 + } } } }