From 5e3659fb8de273d535ea43e75dd6a9ab774f1013 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 17 May 2026 23:08:08 -0400 Subject: [PATCH] Promote cornerRadius + focus tokens to qs.Commons.Style singleton --- .../omarchy-shell/Commons/Style.qml | 51 +++++++++++++++++++ .../quickshell/omarchy-shell/Commons/qmldir | 1 + .../omarchy-shell/Ui/CursorSurface.qml | 3 +- .../omarchy-shell/Ui/KeyboardPanel.qml | 2 +- .../omarchy-shell/Ui/PanelActionButton.qml | 3 +- .../omarchy-shell/Ui/PillButton.qml | 3 +- .../quickshell/omarchy-shell/Ui/PopupCard.qml | 2 +- .../plugins/settings/SettingsPanel.qml | 44 ++++------------ 8 files changed, 69 insertions(+), 40 deletions(-) create mode 100644 default/quickshell/omarchy-shell/Commons/Style.qml diff --git a/default/quickshell/omarchy-shell/Commons/Style.qml b/default/quickshell/omarchy-shell/Commons/Style.qml new file mode 100644 index 00000000..5ab404cc --- /dev/null +++ b/default/quickshell/omarchy-shell/Commons/Style.qml @@ -0,0 +1,51 @@ +pragma Singleton +import QtQuick +import Quickshell +import Quickshell.Io + +// Shared structural style tokens for the shell. Color is the palette +// singleton; Style holds the *shape* and *focus-affordance* tokens that +// every panel surface and qs.Ui component should bind to so they stay +// in sync as the user toggles round/sharp corners or as themes change. +// +// `cornerRadius` is mirrored from ~/.local/state/omarchy/toggles/quickshell-menu.json. +// `omarchy style corners ` writes that file; we watch it and +// hot-reload the binding here so every consumer rerenders. +QtObject { + id: root + + property int cornerRadius: 0 + + // Focus affordances. Deliberately distinct from "selected" (which uses an + // accent fill) so the keyboard cursor never reads as the chosen value. + // The settings panel originated these tokens; promoting them here means + // every Ui component picks them up uniformly. + readonly property color focusBorderColor: Color.accent + readonly property color focusFillColor: Qt.rgba(Color.accent.r, Color.accent.g, Color.accent.b, 0.22) + readonly property int focusBorderWidth: 3 + + // Convenience: the standard "hot" (hover or keyboard cursor) tint used by + // PillButton, PanelActionButton, etc. Foreground at 0.12 alpha matches the + // value PillButton was already painting before promotion. + readonly property color hotFill: Qt.rgba(Color.foreground.r, Color.foreground.g, Color.foreground.b, 0.12) + + function loadStyleState(raw) { + try { + var s = JSON.parse(raw || "{}") + var n = Number(s.radius) + cornerRadius = isFinite(n) ? n : 0 + } catch (e) { + cornerRadius = 0 + } + } + + property FileView styleStateFile: FileView { + id: styleStateFile + path: Quickshell.env("HOME") + "/.local/state/omarchy/toggles/quickshell-menu.json" + watchChanges: true + printErrors: false + onLoaded: root.loadStyleState(text()) + onLoadFailed: root.loadStyleState("") + onFileChanged: reload() + } +} diff --git a/default/quickshell/omarchy-shell/Commons/qmldir b/default/quickshell/omarchy-shell/Commons/qmldir index 2f66f1fb..807c744f 100644 --- a/default/quickshell/omarchy-shell/Commons/qmldir +++ b/default/quickshell/omarchy-shell/Commons/qmldir @@ -1,2 +1,3 @@ module qs.Commons singleton Color 1.0 Color.qml +singleton Style 1.0 Style.qml diff --git a/default/quickshell/omarchy-shell/Ui/CursorSurface.qml b/default/quickshell/omarchy-shell/Ui/CursorSurface.qml index 3cef8f64..477d4e32 100644 --- a/default/quickshell/omarchy-shell/Ui/CursorSurface.qml +++ b/default/quickshell/omarchy-shell/Ui/CursorSurface.qml @@ -1,4 +1,5 @@ import QtQuick +import qs.Commons // Shared visual chrome for keyboard-and-mouse-navigable items inside a panel. // Contract: items must NOT read `containsMouse` for color/border. Mouse @@ -14,7 +15,7 @@ Rectangle { property color foreground: "#cacccc" property color fill: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.18) - radius: 4 + radius: Style.cornerRadius color: (hasCursor || current) ? fill : "transparent" border.width: hasCursor ? 1 : 0 border.color: foreground diff --git a/default/quickshell/omarchy-shell/Ui/KeyboardPanel.qml b/default/quickshell/omarchy-shell/Ui/KeyboardPanel.qml index ed018fe6..a3228351 100644 --- a/default/quickshell/omarchy-shell/Ui/KeyboardPanel.qml +++ b/default/quickshell/omarchy-shell/Ui/KeyboardPanel.qml @@ -193,7 +193,7 @@ PanelWindow { color: Color.popups.background border.color: Color.popups.border border.width: 2 - radius: 0 + radius: Style.cornerRadius opacity: root.open ? 1.0 : 0 Behavior on opacity { NumberAnimation { duration: 140; easing.type: Easing.OutCubic } diff --git a/default/quickshell/omarchy-shell/Ui/PanelActionButton.qml b/default/quickshell/omarchy-shell/Ui/PanelActionButton.qml index 5bd5e16b..abd4c140 100644 --- a/default/quickshell/omarchy-shell/Ui/PanelActionButton.qml +++ b/default/quickshell/omarchy-shell/Ui/PanelActionButton.qml @@ -1,4 +1,5 @@ import QtQuick +import qs.Commons // Small (22×22 by default) icon button used at the right edge of panel rows // for inline actions — forget network, confirm passphrase, unpair device, @@ -27,7 +28,7 @@ Rectangle { implicitWidth: size implicitHeight: size - radius: 4 + radius: Style.cornerRadius color: mouse.containsMouse && root.enabled ? Qt.rgba(hoverColor.r, hoverColor.g, hoverColor.b, 0.20) diff --git a/default/quickshell/omarchy-shell/Ui/PillButton.qml b/default/quickshell/omarchy-shell/Ui/PillButton.qml index 0df3dd74..65acc241 100644 --- a/default/quickshell/omarchy-shell/Ui/PillButton.qml +++ b/default/quickshell/omarchy-shell/Ui/PillButton.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Controls +import qs.Commons Rectangle { id: root @@ -58,7 +59,7 @@ Rectangle { implicitWidth: row.implicitWidth + horizontalPadding * 2 implicitHeight: row.implicitHeight + verticalPadding * 2 - radius: 4 + radius: Style.cornerRadius // Hot = mouse hover OR keyboard cursor. Pressed wins over both; otherwise // hot beats `active` (so a cursor on an already-active pill still reads diff --git a/default/quickshell/omarchy-shell/Ui/PopupCard.qml b/default/quickshell/omarchy-shell/Ui/PopupCard.qml index 6a2aada5..e3fae94e 100644 --- a/default/quickshell/omarchy-shell/Ui/PopupCard.qml +++ b/default/quickshell/omarchy-shell/Ui/PopupCard.qml @@ -119,7 +119,7 @@ PopupWindow { color: Color.popups.background border.color: Color.popups.border border.width: 2 - radius: 0 + radius: Style.cornerRadius opacity: root.open ? 1.0 : 0 Behavior on opacity { diff --git a/default/quickshell/omarchy-shell/plugins/settings/SettingsPanel.qml b/default/quickshell/omarchy-shell/plugins/settings/SettingsPanel.qml index 112e508c..79ba000e 100644 --- a/default/quickshell/omarchy-shell/plugins/settings/SettingsPanel.qml +++ b/default/quickshell/omarchy-shell/plugins/settings/SettingsPanel.qml @@ -43,7 +43,6 @@ Item { readonly property string home: Quickshell.env("HOME") readonly property string userConfigPath: home + "/.config/omarchy/shell.json" readonly property string defaultsPath: omarchyPath + "/default/quickshell/omarchy-shell/shell-defaults.json" - readonly property string styleStatePath: home + "/.local/state/omarchy/toggles/quickshell-menu.json" // ---------------- theme -------------------------------------------------- // Bar settings deliberately isn't a themable surface in shell.toml — it @@ -54,22 +53,15 @@ Item { property color urgent: Color.urgent property string fontFamily: "monospace" - // Source-of-truth for the shell-wide corner radius. Mirrors what the menu - // reads from quickshell-menu.json so `omarchy style corners ` - // flips both surfaces together. - property int cornerRadius: 0 - - // ---------------- keyboard focus ----------------------------------------- - // Keyboard navigation walks the bar form directly; this panel no longer has - // side navigation because it only edits the bar. - - // Focus visuals — deliberately *different* from selected styling so the - // keyboard cursor never gets confused with the current value/choice. A - // selected control gets a 2px accent border; a focused control gets a 3px - // accent border plus a noticeably tinted accent background. - readonly property color focusBorderColor: accent - readonly property color focusFillColor: Qt.rgba(accent.r, accent.g, accent.b, 0.22) - readonly property int focusBorderWidth: 3 + // Structural style tokens live on the shared Style singleton so toggling + // `omarchy style corners` and theme swaps update every consumer at once. + // Aliasing them as readonly properties keeps the existing inline component + // bindings (`root.cornerRadius`, `root.focusBorderColor`, ...) working + // without sprinkling Style.* across the file. + readonly property int cornerRadius: Style.cornerRadius + readonly property color focusBorderColor: Style.focusBorderColor + readonly property color focusFillColor: Style.focusFillColor + readonly property int focusBorderWidth: Style.focusBorderWidth // Move activeFocus to a dedicated sink Item that lives outside the body // tree. Just clearing focus on the previously focused descendant isn't @@ -312,16 +304,6 @@ Item { mutateSection(section, function(a) { a[index] = cloneJson(newEntry) }) } - function loadStyleState(raw) { - try { - var s = JSON.parse(raw || "{}") - var n = Number(s.radius) - cornerRadius = isFinite(n) ? n : 0 - } catch (e) { - cornerRadius = 0 - } - } - // ---------------- widget catalog ----------------------------------------- readonly property var legacyWidgetMeta: ({ "omarchy": { name: "Omarchy menu", description: "Launches the Omarchy menu", category: "Compositor" }, @@ -486,14 +468,6 @@ Item { onFileChanged: reload() } - FileView { - path: root.styleStatePath - watchChanges: true - printErrors: false - onLoaded: root.loadStyleState(text()) - onFileChanged: reload() - } - // ---------------- window ------------------------------------------------- FloatingWindow { id: window