From 6a8a9172b1a98580390a28564908691273871e11 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 11 Aug 2025 20:33:01 +0700 Subject: [PATCH] bar tooltips: refractor tooltip bg to StyledPopup --- .../ii/modules/bar/BatteryIndicator.qml | 3 +- .../ii/modules/bar/BatteryPopup.qml | 214 +++++++++--------- .../quickshell/ii/modules/bar/ClockWidget.qml | 109 ++++----- .../quickshell/ii/modules/bar/Resource.qml | 91 ++++---- .../ii/modules/bar/weather/WeatherBar.qml | 3 +- .../ii/modules/bar/weather/WeatherPopup.qml | 155 ++++++------- .../ii/modules/common/widgets/StyledPopup.qml | 24 +- 7 files changed, 284 insertions(+), 315 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/BatteryIndicator.qml b/.config/quickshell/ii/modules/bar/BatteryIndicator.qml index d2f17e598..5172b5891 100644 --- a/.config/quickshell/ii/modules/bar/BatteryIndicator.qml +++ b/.config/quickshell/ii/modules/bar/BatteryIndicator.qml @@ -97,7 +97,8 @@ MouseArea { StyledPopup { hoverTarget: root - contentComponent: BatteryPopup { + + BatteryPopup { id: batteryPopup anchors.centerIn: parent } diff --git a/.config/quickshell/ii/modules/bar/BatteryPopup.qml b/.config/quickshell/ii/modules/bar/BatteryPopup.qml index cfe16ef73..9b9edc5a1 100644 --- a/.config/quickshell/ii/modules/bar/BatteryPopup.qml +++ b/.config/quickshell/ii/modules/bar/BatteryPopup.qml @@ -5,134 +5,124 @@ import qs import QtQuick import QtQuick.Layouts -Rectangle { - id: root - readonly property real margin: 10 - implicitWidth: columnLayout.implicitWidth + margin * 2 - implicitHeight: columnLayout.implicitHeight + margin * 2 - color: Appearance.colors.colSurfaceContainer - radius: Appearance.rounding.small - clip: true +ColumnLayout { + id: columnLayout + anchors.centerIn: parent + spacing: 4 - ColumnLayout { - id: columnLayout - anchors.centerIn: parent - spacing: 4 + // Header + RowLayout { + id: header + spacing: 5 - // Header - RowLayout { - id: header - spacing: 5 + MaterialSymbol { + fill: 0 + font.weight: Font.Medium + text: "battery_android_full" + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant + } - MaterialSymbol { - fill: 0 - font.weight: Font.Medium - text: "battery_android_full" - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnSurfaceVariant + StyledText { + text: "Battery" + font { + weight: Font.Medium + pixelSize: Appearance.font.pixelSize.normal } + color: Appearance.colors.colOnSurfaceVariant + } + } - StyledText { - text: "Battery" - font { - weight: Font.Medium - pixelSize: Appearance.font.pixelSize.normal - } - color: Appearance.colors.colOnSurfaceVariant + // This row is hidden when the battery is full. + RowLayout { + spacing: 5 + Layout.fillWidth: true + property bool rowVisible: { + let timeValue = Battery.isCharging ? Battery.timeToFull : Battery.timeToEmpty; + let power = Battery.energyRate; + return !(Battery.chargeState == 4 || timeValue <= 0 || power <= 0.01); + } + visible: rowVisible + opacity: rowVisible ? 1 : 0 + Behavior on opacity { + NumberAnimation { + duration: 500 } } - // This row is hidden when the battery is full. - RowLayout { - spacing: 5 + MaterialSymbol { + text: "schedule" + color: Appearance.colors.colOnSurfaceVariant + iconSize: Appearance.font.pixelSize.large + } + StyledText { + text: Battery.isCharging ? Translation.tr("Time to full:") : Translation.tr("Time to empty:") + color: Appearance.colors.colOnSurfaceVariant + } + StyledText { Layout.fillWidth: true - property bool rowVisible: { - let timeValue = Battery.isCharging ? Battery.timeToFull : Battery.timeToEmpty; - let power = Battery.energyRate; - return !(Battery.chargeState == 4 || timeValue <= 0 || power <= 0.01); - } - visible: rowVisible - opacity: rowVisible ? 1 : 0 - Behavior on opacity { - NumberAnimation { - duration: 500 - } - } - - MaterialSymbol { - text: "schedule" - color: Appearance.colors.colOnSurfaceVariant - iconSize: Appearance.font.pixelSize.large - } - StyledText { - text: Battery.isCharging ? Translation.tr("Time to full:") : Translation.tr("Time to empty:") - color: Appearance.colors.colOnSurfaceVariant - } - StyledText { - Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - color: Appearance.colors.colOnSurfaceVariant - text: { - function formatTime(seconds) { - var h = Math.floor(seconds / 3600); - var m = Math.floor((seconds % 3600) / 60); - if (h > 0) - return `${h}h, ${m}m`; - else - return `${m}m`; - } - if (Battery.isCharging) - return formatTime(Battery.timeToFull); + horizontalAlignment: Text.AlignRight + color: Appearance.colors.colOnSurfaceVariant + text: { + function formatTime(seconds) { + var h = Math.floor(seconds / 3600); + var m = Math.floor((seconds % 3600) / 60); + if (h > 0) + return `${h}h, ${m}m`; else - return formatTime(Battery.timeToEmpty); + return `${m}m`; } + if (Battery.isCharging) + return formatTime(Battery.timeToFull); + else + return formatTime(Battery.timeToEmpty); + } + } + } + + RowLayout { + spacing: 5 + Layout.fillWidth: true + + property bool rowVisible: !(Battery.chargeState != 4 && Battery.energyRate == 0) + visible: rowVisible + opacity: rowVisible ? 1 : 0 + Behavior on opacity { + NumberAnimation { + duration: 500 } } - RowLayout { - spacing: 5 + MaterialSymbol { + text: "bolt" + color: Appearance.colors.colOnSurfaceVariant + iconSize: Appearance.font.pixelSize.large + } + + StyledText { + text: { + if (Battery.chargeState == 4) { + return Translation.tr("Fully charged"); + } else if (Battery.chargeState == 1) { + return Translation.tr("Charging:"); + } else { + return Translation.tr("Discharging:"); + } + } + color: Appearance.colors.colOnSurfaceVariant + } + + StyledText { Layout.fillWidth: true - - property bool rowVisible: !(Battery.chargeState != 4 && Battery.energyRate == 0) - visible: rowVisible - opacity: rowVisible ? 1 : 0 - Behavior on opacity { - NumberAnimation { - duration: 500 - } - } - - MaterialSymbol { - text: "bolt" - color: Appearance.colors.colOnSurfaceVariant - iconSize: Appearance.font.pixelSize.large - } - - StyledText { - text: { - if (Battery.chargeState == 4) { - return Translation.tr("Fully charged"); - } else if (Battery.chargeState == 1) { - return Translation.tr("Charging:"); - } else { - return Translation.tr("Discharging:"); - } - } - color: Appearance.colors.colOnSurfaceVariant - } - - StyledText { - Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - color: Appearance.colors.colOnSurfaceVariant - text: { - if (Battery.chargeState == 4) { - return ""; - } else { - return `${Battery.energyRate.toFixed(2)}W`; - } + horizontalAlignment: Text.AlignRight + color: Appearance.colors.colOnSurfaceVariant + text: { + if (Battery.chargeState == 4) { + return ""; + } else { + return `${Battery.energyRate.toFixed(2)}W`; } } } } -} +} \ No newline at end of file diff --git a/.config/quickshell/ii/modules/bar/ClockWidget.qml b/.config/quickshell/ii/modules/bar/ClockWidget.qml index 1523cebd2..973039116 100644 --- a/.config/quickshell/ii/modules/bar/ClockWidget.qml +++ b/.config/quickshell/ii/modules/bar/ClockWidget.qml @@ -75,72 +75,63 @@ Item { StyledPopup { hoverTarget: mouseArea - contentComponent: Rectangle { - id: datePopup - readonly property real margin: 12 - implicitWidth: columnLayout.implicitWidth + margin * 2 - implicitHeight: columnLayout.implicitHeight + margin * 2 - color: Appearance.colors.colSurfaceContainer - radius: Appearance.rounding.small - clip: true + + ColumnLayout { + id: columnLayout + anchors.centerIn: parent + spacing: 4 + // Date + Time row + RowLayout { + spacing: 5 + + MaterialSymbol { + fill: 0 + font.weight: Font.Medium + text: "calendar_month" + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant + } + StyledText { + horizontalAlignment: Text.AlignLeft + color: Appearance.colors.colOnSurfaceVariant + text: `${root.formattedDate} • ${root.formattedTime}` + font.weight: Font.Medium + } + } + + // Uptime row + RowLayout { + spacing: 5 + Layout.fillWidth: true + MaterialSymbol { text: "timelapse"; color: Appearance.colors.colOnSurfaceVariant; font.pixelSize: Appearance.font.pixelSize.large } + StyledText { text: Translation.tr("System uptime:"); color: Appearance.colors.colOnSurfaceVariant } + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + color: Appearance.colors.colOnSurfaceVariant + text: root.formattedUptime + } + } + + // Tasks ColumnLayout { - id: columnLayout - anchors.centerIn: parent - spacing: 4 + spacing: 0 + Layout.fillWidth: true - // Date + Time row RowLayout { - spacing: 5 - - MaterialSymbol { - fill: 0 - font.weight: Font.Medium - text: "calendar_month" - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnSurfaceVariant - } - StyledText { - horizontalAlignment: Text.AlignLeft - color: Appearance.colors.colOnSurfaceVariant - text: `${root.formattedDate} • ${root.formattedTime}` - font.weight: Font.Medium - } + spacing: 4 + Layout.fillWidth: true + MaterialSymbol { text: "checklist"; color: Appearance.colors.colOnSurfaceVariant; font.pixelSize: Appearance.font.pixelSize.large } + StyledText { text: Translation.tr("To Do:"); color: Appearance.colors.colOnSurfaceVariant } } - // Uptime row - RowLayout { - spacing: 5 + StyledText { Layout.fillWidth: true - MaterialSymbol { text: "timelapse"; color: Appearance.colors.colOnSurfaceVariant; font.pixelSize: Appearance.font.pixelSize.large } - StyledText { text: Translation.tr("System uptime:"); color: Appearance.colors.colOnSurfaceVariant } - StyledText { - Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - color: Appearance.colors.colOnSurfaceVariant - text: root.formattedUptime - } - } - - // Tasks - ColumnLayout { - spacing: 0 - Layout.fillWidth: true - - RowLayout { - spacing: 4 - Layout.fillWidth: true - MaterialSymbol { text: "checklist"; color: Appearance.colors.colOnSurfaceVariant; font.pixelSize: Appearance.font.pixelSize.large } - StyledText { text: Translation.tr("To Do:"); color: Appearance.colors.colOnSurfaceVariant } - } - - StyledText { - Layout.fillWidth: true - horizontalAlignment: Text.AlignLeft - wrapMode: Text.Wrap - color: Appearance.colors.colOnSurfaceVariant - text: root.todosSection - } + horizontalAlignment: Text.AlignLeft + wrapMode: Text.Wrap + color: Appearance.colors.colOnSurfaceVariant + text: root.todosSection } } } diff --git a/.config/quickshell/ii/modules/bar/Resource.qml b/.config/quickshell/ii/modules/bar/Resource.qml index 8b0eb1633..a57501335 100644 --- a/.config/quickshell/ii/modules/bar/Resource.qml +++ b/.config/quickshell/ii/modules/bar/Resource.qml @@ -70,70 +70,61 @@ Item { StyledPopup { hoverTarget: mouseArea - contentComponent: Rectangle { - id: resourcePopup - readonly property real margin: 10 - implicitWidth: columnLayout.implicitWidth + margin * 2 - implicitHeight: columnLayout.implicitHeight + margin * 2 - color: Appearance.colors.colSurfaceContainer - radius: Appearance.rounding.small - clip: true + + ColumnLayout { + id: columnLayout + anchors.centerIn: parent + spacing: 4 - ColumnLayout { - id: columnLayout - anchors.centerIn: parent - spacing: 4 + // Header + RowLayout { + id: header + spacing: 5 - // Header - RowLayout { - id: header + MaterialSymbol { + fill: 0 + font.weight: Font.Medium + text: root.tooltipHeaderIcon + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant + } + + StyledText { + text: root.tooltipHeaderText + font { + weight: Font.Medium + pixelSize: Appearance.font.pixelSize.normal + } + color: Appearance.colors.colOnSurfaceVariant + } + } + + // Info rows + Repeater { + model: root.tooltipData + delegate: RowLayout { spacing: 5 + Layout.fillWidth: true MaterialSymbol { - fill: 0 - font.weight: Font.Medium - text: root.tooltipHeaderIcon + text: modelData.icon + color: Appearance.colors.colOnSurfaceVariant iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnSurfaceVariant } - StyledText { - text: root.tooltipHeaderText - font { - weight: Font.Medium - pixelSize: Appearance.font.pixelSize.normal - } + text: modelData.label color: Appearance.colors.colOnSurfaceVariant } - } - - // Info rows - Repeater { - model: root.tooltipData - delegate: RowLayout { - spacing: 5 + StyledText { Layout.fillWidth: true - - MaterialSymbol { - text: modelData.icon - color: Appearance.colors.colOnSurfaceVariant - iconSize: Appearance.font.pixelSize.large - } - StyledText { - text: modelData.label - color: Appearance.colors.colOnSurfaceVariant - } - StyledText { - Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - visible: modelData.value !== "" - color: Appearance.colors.colOnSurfaceVariant - text: modelData.value - } + horizontalAlignment: Text.AlignRight + visible: modelData.value !== "" + color: Appearance.colors.colOnSurfaceVariant + text: modelData.value } } - } + } } diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml index 8339d4829..42fe8b195 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml @@ -38,7 +38,8 @@ MouseArea { StyledPopup { hoverTarget: root - contentComponent: WeatherPopup { + + WeatherPopup { id: weatherPopup anchors.centerIn: parent } diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml index 1e7c39504..6297ea8cc 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml @@ -6,94 +6,83 @@ import qs.modules.common.widgets import QtQuick import QtQuick.Layouts -Rectangle { - id: root - readonly property real margin: 10 - implicitWidth: columnLayout.implicitWidth + margin * 2 - implicitHeight: columnLayout.implicitHeight + margin * 2 - color: Appearance.colors.colSurfaceContainer - radius: Appearance.rounding.small - clip: true +ColumnLayout { + id: columnLayout + spacing: 5 + implicitWidth: Math.max(header.implicitWidth, gridLayout.implicitWidth) + implicitHeight: gridLayout.implicitHeight - ColumnLayout { - id: columnLayout + // Header + RowLayout { + id: header spacing: 5 - anchors.centerIn: root - implicitWidth: Math.max(header.implicitWidth, gridLayout.implicitWidth) - implicitHeight: gridLayout.implicitHeight + Layout.alignment: Qt.AlignHCenter - // Header - RowLayout { - id: header - spacing: 5 - Layout.alignment: Qt.AlignHCenter - - MaterialSymbol { - fill: 0 - font.weight: Font.Medium - text: "location_on" - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnSurfaceVariant - } - - StyledText { - text: Weather.data.city - font { - weight: Font.Medium - pixelSize: Appearance.font.pixelSize.normal - } - color: Appearance.colors.colOnSurfaceVariant - } + MaterialSymbol { + fill: 0 + font.weight: Font.Medium + text: "location_on" + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant } - // Metrics grid - GridLayout { - id: gridLayout - columns: 2 - rowSpacing: 5 - columnSpacing: 5 - uniformCellWidths: true - - WeatherCard { - title: Translation.tr("UV Index") - symbol: "wb_sunny" - value: Weather.data.uv - } - WeatherCard { - title: Translation.tr("Wind") - symbol: "air" - value: `(${Weather.data.windDir}) ${Weather.data.wind}` - } - WeatherCard { - title: Translation.tr("Precipitation") - symbol: "rainy_light" - value: Weather.data.precip - } - WeatherCard { - title: Translation.tr("Humidity") - symbol: "humidity_low" - value: Weather.data.humidity - } - WeatherCard { - title: Translation.tr("Visibility") - symbol: "visibility" - value: Weather.data.visib - } - WeatherCard { - title: Translation.tr("Pressure") - symbol: "readiness_score" - value: Weather.data.press - } - WeatherCard { - title: Translation.tr("Sunrise") - symbol: "wb_twilight" - value: Weather.data.sunrise - } - WeatherCard { - title: Translation.tr("Sunset") - symbol: "bedtime" - value: Weather.data.sunset + StyledText { + text: Weather.data.city + font { + weight: Font.Medium + pixelSize: Appearance.font.pixelSize.normal } + color: Appearance.colors.colOnSurfaceVariant } } -} + + // Metrics grid + GridLayout { + id: gridLayout + columns: 2 + rowSpacing: 5 + columnSpacing: 5 + uniformCellWidths: true + + WeatherCard { + title: Translation.tr("UV Index") + symbol: "wb_sunny" + value: Weather.data.uv + } + WeatherCard { + title: Translation.tr("Wind") + symbol: "air" + value: `(${Weather.data.windDir}) ${Weather.data.wind}` + } + WeatherCard { + title: Translation.tr("Precipitation") + symbol: "rainy_light" + value: Weather.data.precip + } + WeatherCard { + title: Translation.tr("Humidity") + symbol: "humidity_low" + value: Weather.data.humidity + } + WeatherCard { + title: Translation.tr("Visibility") + symbol: "visibility" + value: Weather.data.visib + } + WeatherCard { + title: Translation.tr("Pressure") + symbol: "readiness_score" + value: Weather.data.press + } + WeatherCard { + title: Translation.tr("Sunrise") + symbol: "wb_twilight" + value: Weather.data.sunrise + } + WeatherCard { + title: Translation.tr("Sunset") + symbol: "bedtime" + value: Weather.data.sunset + } + } +} \ No newline at end of file diff --git a/.config/quickshell/ii/modules/common/widgets/StyledPopup.qml b/.config/quickshell/ii/modules/common/widgets/StyledPopup.qml index 85ca0c532..028e0033d 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledPopup.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledPopup.qml @@ -10,8 +10,8 @@ import Quickshell.Wayland LazyLoader { id: root - property Item hoverTarget - property Component contentComponent + property MouseArea hoverTarget + default property Item contentItem active: hoverTarget && hoverTarget.containsMouse @@ -25,13 +25,13 @@ LazyLoader { anchors.top: !Config.options.bar.bottom anchors.bottom: Config.options.bar.bottom - implicitWidth: popupContent.implicitWidth - implicitHeight: popupContent.implicitHeight + implicitWidth: popupBackground.implicitWidth + implicitHeight: popupBackground.implicitHeight margins { left: root.QsWindow?.mapFromItem( root.hoverTarget, - (root.hoverTarget.width - popupContent.implicitWidth) / 2, 0 + (root.hoverTarget.width - popupBackground.implicitWidth) / 2, 0 ).x top: Appearance.sizes.hyprlandGapsOut bottom: Appearance.sizes.hyprlandGapsOut @@ -39,10 +39,16 @@ LazyLoader { WlrLayershell.namespace: "quickshell:popup" WlrLayershell.layer: WlrLayer.Overlay - Loader { - id: popupContent - sourceComponent: root.contentComponent - anchors.centerIn: parent + Rectangle { + id: popupBackground + readonly property real margin: 10 + color: Appearance.colors.colSurfaceContainer + radius: Appearance.rounding.small + + implicitWidth: root.contentItem.implicitWidth + margin * 2 + implicitHeight: root.contentItem.implicitHeight + margin * 2 + + children: [root.contentItem] } } }