From a0cdafc0e2095e297a64c0f7affa109d87118a37 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 5 Nov 2025 00:54:22 -0500 Subject: [PATCH] NTabBar + NTabBarButton --- Modules/Settings/Tabs/BarTab.qml | 10 ++-- Modules/Wallpaper/WallpaperPanel.qml | 54 +++------------------- Widgets/NTabBar.qml | 28 ++++++++++++ Widgets/NTabButton.qml | 68 ++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 51 deletions(-) create mode 100644 Widgets/NTabBar.qml create mode 100644 Widgets/NTabButton.qml diff --git a/Modules/Settings/Tabs/BarTab.qml b/Modules/Settings/Tabs/BarTab.qml index 5f957b7c..38c8dbd0 100644 --- a/Modules/Settings/Tabs/BarTab.qml +++ b/Modules/Settings/Tabs/BarTab.qml @@ -124,18 +124,21 @@ ColumnLayout { } // Monitor tabs - only visible when not syncing - TabBar { + NTabBar { id: monitorTabBar Layout.fillWidth: true visible: !Settings.data.bar.syncAcrossMonitors + currentIndex: currentMonitorIndex + onCurrentIndexChanged: currentMonitorIndex = currentIndex Repeater { model: Quickshell.screens - TabButton { + NTabButton { required property var modelData required property int index text: modelData.name - onClicked: currentMonitorIndex = index + tabIndex: index + checked: monitorTabBar.currentIndex === index } } } @@ -150,6 +153,7 @@ ColumnLayout { NToggle { Layout.fillWidth: true visible: !Settings.data.bar.syncAcrossMonitors + //TODO TRANSLATE label: `Show bar on ${currentMonitorName}` description: `Enable or disable the bar on this monitor` checked: (Settings.data.bar.monitors || []).length === 0 || (Settings.data.bar.monitors || []).indexOf(currentMonitorName) !== -1 diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml index cbb387b2..799caea2 100644 --- a/Modules/Wallpaper/WallpaperPanel.qml +++ b/Modules/Wallpaper/WallpaperPanel.qml @@ -222,7 +222,7 @@ NPanel { } // Monitor tabs - TabBar { + NTabBar { id: screenTabBar visible: !Settings.data.wallpaper.setWallpaperOnAllMonitors || Settings.data.wallpaper.enableMultiMonitorDirectories Layout.fillWidth: true @@ -230,56 +230,14 @@ NPanel { onCurrentIndexChanged: currentScreenIndex = currentIndex spacing: Style.marginM - background: Rectangle { - color: Color.transparent - } - Repeater { model: Quickshell.screens - delegate: TabButton { + NTabButton { + required property var modelData + required property int index text: modelData.name || `Screen ${index + 1}` - width: implicitWidth + Style.marginS * 2 - - background: Rectangle { - color: screenTabBar.currentIndex === index ? Color.mSecondary : Color.transparent - radius: Style.radiusS - border.width: screenTabBar.currentIndex === index ? 0 : Style.borderS - border.color: Color.mOutline - - Behavior on color { - ColorAnimation { - duration: Style.animationFast - } - } - } - - contentItem: NText { - text: parent.text - pointSize: Style.fontSizeL - font.weight: screenTabBar.currentIndex === index ? Style.fontWeightBold : Style.fontWeightRegular - family: Settings.data.ui.fontDefault - color: screenTabBar.currentIndex === index ? Color.mOnSecondary : Color.mOnSurfaceVariant - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - - // Add hover effect - HoverHandler { - id: tabHover - } - - Rectangle { - anchors.fill: parent - color: Color.mOnSurface - opacity: tabHover.hovered && screenTabBar.currentIndex !== index ? 0.08 : 0 - radius: Style.radiusS - - Behavior on opacity { - NumberAnimation { - duration: Style.animationFast - } - } - } + tabIndex: index + checked: screenTabBar.currentIndex === index } } } diff --git a/Widgets/NTabBar.qml b/Widgets/NTabBar.qml new file mode 100644 index 00000000..db218606 --- /dev/null +++ b/Widgets/NTabBar.qml @@ -0,0 +1,28 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import qs.Commons +import qs.Services +import qs.Widgets + +Rectangle { + id: root + + // Public properties + property int currentIndex: 0 + property int spacing: Style.marginS + default property alias content: tabRow.children + + // Styling + Layout.fillWidth: true + implicitHeight: Style.baseWidgetSize + Style.marginXS * 2 + color: Color.mSurfaceVariant + radius: Style.radiusS + + RowLayout { + id: tabRow + anchors.fill: parent + anchors.margins: Style.marginXS + spacing: root.spacing + } +} diff --git a/Widgets/NTabButton.qml b/Widgets/NTabButton.qml new file mode 100644 index 00000000..d9415836 --- /dev/null +++ b/Widgets/NTabButton.qml @@ -0,0 +1,68 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import qs.Commons +import qs.Services +import qs.Widgets + +Rectangle { + id: root + + // Public properties + property string text: "" + property bool checked: false + property int tabIndex: 0 + + // Internal state + property bool isHovered: false + + signal clicked + + // Sizing + Layout.fillWidth: true + Layout.fillHeight: true + + // Styling + radius: Style.radiusXS + color: root.checked ? Color.mPrimary : (root.isHovered ? Color.mHover : Color.mSurface) + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + + NText { + id: tabText + anchors.centerIn: parent + text: root.text + pointSize: Style.fontSizeM + font.weight: root.checked ? Style.fontWeightSemiBold : Style.fontWeightRegular + color: root.checked ? Color.mOnPrimary : root.isHovered ? Color.mOnHover : Color.mOnSurface + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onEntered: root.isHovered = true + onExited: root.isHovered = false + onClicked: { + root.clicked() + // Update parent NTabBar's currentIndex + if (root.parent && root.parent.parent && root.parent.parent.currentIndex !== undefined) { + root.parent.parent.currentIndex = root.tabIndex + } + } + } +}