From 3c4749ead0ef30237330cc56437990164b575c76 Mon Sep 17 00:00:00 2001 From: bbedward Date: Tue, 3 Feb 2026 11:03:33 -0500 Subject: [PATCH] widgets: add a button color setting --- quickshell/Common/SettingsData.qml | 1 + quickshell/Common/Theme.qml | 52 +++++++++++++++++++ quickshell/Common/settings/SettingsSpec.js | 1 + .../Modals/Settings/SettingsSidebar.qml | 24 ++++----- .../Modules/Settings/ThemeColorsTab.qml | 32 ++++++++++++ quickshell/Widgets/DankButton.qml | 4 +- quickshell/Widgets/DankButtonGroup.qml | 10 ++-- 7 files changed, 105 insertions(+), 19 deletions(-) diff --git a/quickshell/Common/SettingsData.qml b/quickshell/Common/SettingsData.qml index 5011a6a8..a82bac62 100644 --- a/quickshell/Common/SettingsData.qml +++ b/quickshell/Common/SettingsData.qml @@ -134,6 +134,7 @@ Singleton { property string widgetBackgroundColor: "sch" property string widgetColorMode: "default" property string controlCenterTileColorMode: "primary" + property string buttonColorMode: "primary" property real cornerRadius: 12 property int niriLayoutGapsOverride: -1 property int niriLayoutRadiusOverride: -1 diff --git a/quickshell/Common/Theme.qml b/quickshell/Common/Theme.qml index d51fde2b..28e4e6f6 100644 --- a/quickshell/Common/Theme.qml +++ b/quickshell/Common/Theme.qml @@ -606,6 +606,58 @@ Singleton { } } + readonly property color buttonBg: { + switch (SettingsData.buttonColorMode) { + case "primaryContainer": + return primaryContainer; + case "secondary": + return secondary; + case "surfaceVariant": + return surfaceVariant; + default: + return primary; + } + } + + readonly property color buttonText: { + switch (SettingsData.buttonColorMode) { + case "primaryContainer": + return primary; + case "secondary": + return surfaceText; + case "surfaceVariant": + return surfaceText; + default: + return primaryText; + } + } + + readonly property color buttonHover: { + switch (SettingsData.buttonColorMode) { + case "primaryContainer": + return Qt.rgba(primary.r, primary.g, primary.b, 0.12); + case "secondary": + return Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.12); + case "surfaceVariant": + return Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.12); + default: + return primaryHover; + } + } + + readonly property color buttonPressed: { + switch (SettingsData.buttonColorMode) { + case "primaryContainer": + return Qt.rgba(primary.r, primary.g, primary.b, 0.16); + case "secondary": + return Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.16); + case "surfaceVariant": + return Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.16); + default: + return primaryPressed; + } + } + property color shadowMedium: Qt.rgba(0, 0, 0, 0.08) property color shadowStrong: Qt.rgba(0, 0, 0, 0.3) diff --git a/quickshell/Common/settings/SettingsSpec.js b/quickshell/Common/settings/SettingsSpec.js index 620ddb31..7f4db101 100644 --- a/quickshell/Common/settings/SettingsSpec.js +++ b/quickshell/Common/settings/SettingsSpec.js @@ -20,6 +20,7 @@ var SPEC = { widgetBackgroundColor: { def: "sch" }, widgetColorMode: { def: "default" }, controlCenterTileColorMode: { def: "primary" }, + buttonColorMode: { def: "primary" }, cornerRadius: { def: 12, onChange: "updateCompositorLayout" }, niriLayoutGapsOverride: { def: -1, onChange: "updateCompositorLayout" }, niriLayoutRadiusOverride: { def: -1, onChange: "updateCompositorLayout" }, diff --git a/quickshell/Modals/Settings/SettingsSidebar.qml b/quickshell/Modals/Settings/SettingsSidebar.qml index ce19dc33..134f9c51 100644 --- a/quickshell/Modals/Settings/SettingsSidebar.qml +++ b/quickshell/Modals/Settings/SettingsSidebar.qml @@ -689,7 +689,7 @@ Rectangle { radius: Theme.cornerRadius color: { if (root.searchSelectedIndex === index) - return Theme.primary; + return Theme.buttonBg; if (resultMouseArea.containsMouse) return Theme.surfaceHover; return "transparent"; @@ -707,7 +707,7 @@ Rectangle { DankIcon { name: resultDelegate.modelData.icon || "settings" size: Theme.iconSize - 2 - color: root.searchSelectedIndex === resultDelegate.index ? Theme.primaryText : Theme.surfaceText + color: root.searchSelectedIndex === resultDelegate.index ? Theme.buttonText : Theme.surfaceText anchors.verticalCenter: parent.verticalCenter } @@ -720,7 +720,7 @@ Rectangle { text: resultDelegate.modelData.label font.pixelSize: Theme.fontSizeMedium font.weight: Font.Medium - color: root.searchSelectedIndex === resultDelegate.index ? Theme.primaryText : Theme.surfaceText + color: root.searchSelectedIndex === resultDelegate.index ? Theme.buttonText : Theme.surfaceText width: parent.width wrapMode: Text.Wrap horizontalAlignment: Text.AlignLeft @@ -729,7 +729,7 @@ Rectangle { StyledText { text: resultDelegate.modelData.category font.pixelSize: Theme.fontSizeSmall - 1 - color: root.searchSelectedIndex === resultDelegate.index ? Theme.withAlpha(Theme.primaryText, 0.7) : Theme.surfaceVariantText + color: root.searchSelectedIndex === resultDelegate.index ? Theme.withAlpha(Theme.buttonText, 0.7) : Theme.surfaceVariantText width: parent.width wrapMode: Text.Wrap horizontalAlignment: Text.AlignLeft @@ -810,9 +810,9 @@ Rectangle { color: { if (isActive) - return Theme.primary; + return Theme.buttonBg; if (isHighlighted) - return Theme.primaryHover; + return Theme.buttonHover; if (categoryMouseArea.containsMouse) return Theme.surfaceHover; return "transparent"; @@ -828,7 +828,7 @@ Rectangle { DankIcon { name: categoryDelegate.modelData.icon || "" size: Theme.iconSize - 2 - color: categoryRow.isActive ? Theme.primaryText : Theme.surfaceText + color: categoryRow.isActive ? Theme.buttonText : Theme.surfaceText anchors.verticalCenter: parent.verticalCenter } @@ -836,7 +836,7 @@ Rectangle { text: categoryDelegate.modelData.text || "" font.pixelSize: Theme.fontSizeMedium font.weight: (categoryRow.isActive || root.isChildActive(categoryDelegate.modelData)) ? Font.Medium : Font.Normal - color: categoryRow.isActive ? Theme.primaryText : Theme.surfaceText + color: categoryRow.isActive ? Theme.buttonText : Theme.surfaceText anchors.verticalCenter: parent.verticalCenter } } @@ -900,9 +900,9 @@ Rectangle { visible: root.isItemVisible(modelData) color: { if (isActive) - return Theme.primary; + return Theme.buttonBg; if (isHighlighted) - return Theme.primaryHover; + return Theme.buttonHover; if (childMouseArea.containsMouse) return Theme.surfaceHover; return "transparent"; @@ -918,7 +918,7 @@ Rectangle { DankIcon { name: childDelegate.modelData.icon || "" size: Theme.iconSize - 4 - color: childDelegate.isActive ? Theme.primaryText : Theme.surfaceVariantText + color: childDelegate.isActive ? Theme.buttonText : Theme.surfaceVariantText anchors.verticalCenter: parent.verticalCenter } @@ -926,7 +926,7 @@ Rectangle { text: childDelegate.modelData.text || "" font.pixelSize: Theme.fontSizeSmall + 1 font.weight: childDelegate.isActive ? Font.Medium : Font.Normal - color: childDelegate.isActive ? Theme.primaryText : Theme.surfaceText + color: childDelegate.isActive ? Theme.buttonText : Theme.surfaceText anchors.verticalCenter: parent.verticalCenter } } diff --git a/quickshell/Modules/Settings/ThemeColorsTab.qml b/quickshell/Modules/Settings/ThemeColorsTab.qml index fa5b970a..84075e78 100644 --- a/quickshell/Modules/Settings/ThemeColorsTab.qml +++ b/quickshell/Modules/Settings/ThemeColorsTab.qml @@ -1516,6 +1516,38 @@ Item { } } + SettingsDropdownRow { + tab: "theme" + tags: ["button", "color", "primary", "accent"] + settingKey: "buttonColorMode" + text: I18n.tr("Button Color") + description: I18n.tr("Color for primary action buttons") + options: [I18n.tr("Primary", "button color option"), I18n.tr("Primary Container", "button color option"), I18n.tr("Secondary", "button color option"), I18n.tr("Surface Variant", "button color option")] + currentValue: { + switch (SettingsData.buttonColorMode) { + case "primaryContainer": + return I18n.tr("Primary Container", "button color option"); + case "secondary": + return I18n.tr("Secondary", "button color option"); + case "surfaceVariant": + return I18n.tr("Surface Variant", "button color option"); + default: + return I18n.tr("Primary", "button color option"); + } + } + onValueChanged: value => { + if (value === I18n.tr("Primary Container", "button color option")) { + SettingsData.set("buttonColorMode", "primaryContainer"); + } else if (value === I18n.tr("Secondary", "button color option")) { + SettingsData.set("buttonColorMode", "secondary"); + } else if (value === I18n.tr("Surface Variant", "button color option")) { + SettingsData.set("buttonColorMode", "surfaceVariant"); + } else { + SettingsData.set("buttonColorMode", "primary"); + } + } + } + SettingsSliderRow { tab: "theme" tags: ["popup", "transparency", "opacity", "modal"] diff --git a/quickshell/Widgets/DankButton.qml b/quickshell/Widgets/DankButton.qml index 6b62ddae..d3ac137c 100644 --- a/quickshell/Widgets/DankButton.qml +++ b/quickshell/Widgets/DankButton.qml @@ -11,8 +11,8 @@ Rectangle { property bool enabled: true property bool hovered: mouseArea.containsMouse property bool pressed: mouseArea.pressed - property color backgroundColor: Theme.primary - property color textColor: Theme.primaryText + property color backgroundColor: Theme.buttonBg + property color textColor: Theme.buttonText property int buttonHeight: 40 property int horizontalPadding: Theme.spacingL diff --git a/quickshell/Widgets/DankButtonGroup.qml b/quickshell/Widgets/DankButtonGroup.qml index 00feb1c8..5c558fc2 100644 --- a/quickshell/Widgets/DankButtonGroup.qml +++ b/quickshell/Widgets/DankButtonGroup.qml @@ -89,7 +89,7 @@ Flow { width: Math.max(contentItem.implicitWidth + root.buttonPadding * 2, root.minButtonWidth) + (selected ? 4 : 0) height: root.buttonHeight - color: selected ? Theme.primary : Theme.surfaceVariant + color: selected ? Theme.buttonBg : Theme.surfaceVariant border.color: "transparent" border.width: 0 @@ -155,9 +155,9 @@ Flow { bottomRightRadius: parent.bottomRightRadius color: { if (pressed) - return selected ? Theme.primaryPressed : Theme.surfaceTextHover; + return selected ? Theme.buttonPressed : Theme.surfaceTextHover; if (hovered) - return selected ? Theme.primaryHover : Theme.surfaceTextHover; + return selected ? Theme.buttonHover : Theme.surfaceTextHover; return "transparent"; } @@ -183,7 +183,7 @@ Flow { id: checkIcon name: "check" size: root.checkIconSize - color: segment.selected ? Theme.primaryText : Theme.surfaceVariantText + color: segment.selected ? Theme.buttonText : Theme.surfaceVariantText visible: root.checkEnabled && segment.selected opacity: segment.selected ? 1 : 0 scale: segment.selected ? 1 : 0.6 @@ -211,7 +211,7 @@ Flow { text: typeof modelData === "string" ? modelData : modelData.text || "" font.pixelSize: root.textSize font.weight: segment.selected ? Font.Medium : Font.Normal - color: segment.selected ? Theme.primaryText : Theme.surfaceVariantText + color: segment.selected ? Theme.buttonText : Theme.surfaceVariantText anchors.verticalCenter: parent.verticalCenter } }