From 3d300067f6e179e03d1983159b81e1c2cfe2fa8c Mon Sep 17 00:00:00 2001 From: Sam Nystrom Date: Fri, 16 Jan 2026 11:04:25 -0500 Subject: refactor qs bar --- .config/quickshell/Modules/BarMusic.qml | 298 ++++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 .config/quickshell/Modules/BarMusic.qml (limited to '.config/quickshell/Modules/BarMusic.qml') diff --git a/.config/quickshell/Modules/BarMusic.qml b/.config/quickshell/Modules/BarMusic.qml new file mode 100644 index 0000000..676fcc9 --- /dev/null +++ b/.config/quickshell/Modules/BarMusic.qml @@ -0,0 +1,298 @@ +import Quickshell +import QtQuick +import QtQuick.Layouts +import qs.Services + +MouseArea { + id: root + anchors.centerIn: parent + height: parent.implicitHeight + width: musicRow.implicitWidth + state: "popup-closed" + + hoverEnabled: true + onEntered: state = "popup-open" + + property string fontFamily: "FiraCode Nerd Font" + property int fontSize: 14 + + property int contractAnimDuration: 150 + + states: [ + State { + name: "popup-closed" + PropertyChanges { target: popup; visible: false } + PropertyChanges { target: musicRow; visible: true; spacing: 4 } + PropertyChanges { target: songContainer; bottomRightRadius: 4; topRightRadius: 4 } + PropertyChanges { target: cavaContainer; bottomLeftRadius: 4; topLeftRadius: 4 } + PropertyChanges { target: song; opacity: 1 } + PropertyChanges { target: cava; opacity: 1 } + PropertyChanges { + target: popupRect + width: musicRow.width + height: 36 + opacity: 0 + border.color: Flexoki.bg + } + }, + State { + name: "popup-open" + PropertyChanges { target: popup; visible: true } + PropertyChanges { target: musicRow; visible: false; spacing: -1 } + PropertyChanges { target: songContainer; bottomRightRadius: 0; topRightRadius: 0 } + PropertyChanges { target: cavaContainer; bottomLeftRadius: 0; topLeftRadius: 0 } + PropertyChanges { target: song; opacity: 0 } + PropertyChanges { target: cava; opacity: 0 } + PropertyChanges { + target: popupRect + width: 700 + height: 500 + opacity: 1 + border.color: Flexoki.ui2 + } + } + ] + + transitions: [ + Transition { + from: "popup-closed" + to: "popup-open" + + SequentialAnimation { + // show immediately so mouseleave works + PropertyAction { target: popup; property: "visible" } + + ParallelAnimation { + NumberAnimation { + target: songContainer + properties: "bottomRightRadius,topRightRadius" + duration: root.contractAnimDuration + easing.type: Easing.InQuad + } + + NumberAnimation { + target: cavaContainer + properties: "bottomLeftRadius,topLeftRadius" + duration: root.contractAnimDuration + easing.type: Easing.InQuad + } + + NumberAnimation { + target: musicRow + property: "spacing" + duration: root.contractAnimDuration + easing.type: Easing.OutQuad + } + + NumberAnimation { + targets: [song, cava] + property: "opacity" + duration: root.contractAnimDuration + easing.type: Easing.OutQuad + } + } + + PropertyAction { target: popupRect; property: "opacity" } + PropertyAction { target: musicRow; property: "visible" } + + ParallelAnimation { + NumberAnimation { + target: popupRect + property: "width" + duration: 250 + easing.type: Easing.OutQuad + } + + SpringAnimation { + target: popupRect + property: "height" + spring: 5 + mass: 0.5 + damping: 0.2 + epsilon: 0.25 + } + + ColorAnimation { + target: popupRect + property: "border.color" + duration: 250 + easing.type: Easing.OutQuad + } + } + } + }, + Transition { + // TODO: this transition flickers sometimes + from: "popup-open" + to: "popup-closed" + + SequentialAnimation { + ParallelAnimation { + NumberAnimation { + target: popupRect + property: "width" + duration: 250 + easing.type: Easing.OutQuad + } + + NumberAnimation { + target: popupRect + property: "height" + duration: 250 + easing.type: Easing.OutQuad + } + + ColorAnimation { + target: popupRect + property: "border.color" + duration: 250 + easing.type: Easing.OutQuad + } + } + + PropertyAction { target: musicRow; property: "visible" } + PropertyAction { target: popup; properties: "visible" } + PropertyAction { target: popupRect; property: "opacity" } + + ParallelAnimation { + NumberAnimation { + target: songContainer + properties: "bottomRightRadius,topRightRadius" + duration: root.contractAnimDuration + easing.type: Easing.InQuad + } + + NumberAnimation { + target: cavaContainer + properties: "bottomLeftRadius,topLeftRadius" + duration: root.contractAnimDuration + easing.type: Easing.InQuad + } + + NumberAnimation { + target: musicRow + property: "spacing" + duration: root.contractAnimDuration + easing.type: Easing.OutQuad + } + + NumberAnimation { + targets: [song, cava] + property: "opacity" + duration: root.contractAnimDuration + easing.type: Easing.OutQuad + } + } + } + }, + ] + + PopupWindow { + id: popup + anchor.item: root + anchor.rect.x: root.width / 2 - width / 2 + anchor.rect.y: 0 + implicitWidth: 1920 + implicitHeight: 600 + color: "transparent" + visible: false + + + Rectangle { + id: popupRect + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + color: Flexoki.bg + border.width: 2 + radius: 18 + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onExited: root.state = "popup-closed" + } + + MusicPopup {} + } + } + + Row { + id: musicRow + anchors.centerIn: parent + height: parent.height + spacing: 4 + + Rectangle { + id: songContainer + implicitWidth: song.implicitWidth + 16*2 + height: parent.height + color: Flexoki.bg + + bottomLeftRadius: 18 + topLeftRadius: 18 + bottomRightRadius: 4 + topRightRadius: 4 + + Text { + id: song + anchors.centerIn: parent + text: { + if (!Song.file) return "Not playing" + var text = Song.file + if (Song.title) { + if (Song.artist) { + text = Song.artist + " – " + Song.title + } else { + text = Song.title + } + } + if (text.length > 60) { + text = text.substring(0, 60) + "…" + } + return text + } + color: Flexoki.tx + font { family: root.fontFamily; pixelSize: root.fontSize } + } + } + + Rectangle { + id: cavaContainer + implicitWidth: cava.implicitWidth + 16*2 + height: parent.height + color: Flexoki.bg + + bottomLeftRadius: 4 + topLeftRadius: 4 + bottomRightRadius: 18 + topRightRadius: 18 + + Row { + id: cava + anchors.centerIn: parent + height: 15 + 4 + spacing: 2 + + Repeater { + model: Cava.heights + + delegate: Rectangle { + required property int modelData + y: 15 - modelData + width: 8 + height: modelData + 4 + radius: 4 + color: Flexoki.tx + + Behavior on height { + NumberAnimation { duration: 1000 / 30; easing.type: Easing.Linear } + } + Behavior on y { + NumberAnimation { duration: 1000 / 30; easing.type: Easing.Linear } + } + } + } + } + } + } +} -- cgit v1.2.3