Promote cornerRadius + focus tokens to qs.Commons.Style singleton
This commit is contained in:
@@ -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 <round|sharp>` 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
module qs.Commons
|
module qs.Commons
|
||||||
singleton Color 1.0 Color.qml
|
singleton Color 1.0 Color.qml
|
||||||
|
singleton Style 1.0 Style.qml
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import qs.Commons
|
||||||
|
|
||||||
// Shared visual chrome for keyboard-and-mouse-navigable items inside a panel.
|
// Shared visual chrome for keyboard-and-mouse-navigable items inside a panel.
|
||||||
// Contract: items must NOT read `containsMouse` for color/border. Mouse
|
// Contract: items must NOT read `containsMouse` for color/border. Mouse
|
||||||
@@ -14,7 +15,7 @@ Rectangle {
|
|||||||
property color foreground: "#cacccc"
|
property color foreground: "#cacccc"
|
||||||
property color fill: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.18)
|
property color fill: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.18)
|
||||||
|
|
||||||
radius: 4
|
radius: Style.cornerRadius
|
||||||
color: (hasCursor || current) ? fill : "transparent"
|
color: (hasCursor || current) ? fill : "transparent"
|
||||||
border.width: hasCursor ? 1 : 0
|
border.width: hasCursor ? 1 : 0
|
||||||
border.color: foreground
|
border.color: foreground
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ PanelWindow {
|
|||||||
color: Color.popups.background
|
color: Color.popups.background
|
||||||
border.color: Color.popups.border
|
border.color: Color.popups.border
|
||||||
border.width: 2
|
border.width: 2
|
||||||
radius: 0
|
radius: Style.cornerRadius
|
||||||
opacity: root.open ? 1.0 : 0
|
opacity: root.open ? 1.0 : 0
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import qs.Commons
|
||||||
|
|
||||||
// Small (22×22 by default) icon button used at the right edge of panel rows
|
// Small (22×22 by default) icon button used at the right edge of panel rows
|
||||||
// for inline actions — forget network, confirm passphrase, unpair device,
|
// for inline actions — forget network, confirm passphrase, unpair device,
|
||||||
@@ -27,7 +28,7 @@ Rectangle {
|
|||||||
|
|
||||||
implicitWidth: size
|
implicitWidth: size
|
||||||
implicitHeight: size
|
implicitHeight: size
|
||||||
radius: 4
|
radius: Style.cornerRadius
|
||||||
|
|
||||||
color: mouse.containsMouse && root.enabled
|
color: mouse.containsMouse && root.enabled
|
||||||
? Qt.rgba(hoverColor.r, hoverColor.g, hoverColor.b, 0.20)
|
? Qt.rgba(hoverColor.r, hoverColor.g, hoverColor.b, 0.20)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import qs.Commons
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
@@ -58,7 +59,7 @@ Rectangle {
|
|||||||
|
|
||||||
implicitWidth: row.implicitWidth + horizontalPadding * 2
|
implicitWidth: row.implicitWidth + horizontalPadding * 2
|
||||||
implicitHeight: row.implicitHeight + verticalPadding * 2
|
implicitHeight: row.implicitHeight + verticalPadding * 2
|
||||||
radius: 4
|
radius: Style.cornerRadius
|
||||||
|
|
||||||
// Hot = mouse hover OR keyboard cursor. Pressed wins over both; otherwise
|
// Hot = mouse hover OR keyboard cursor. Pressed wins over both; otherwise
|
||||||
// hot beats `active` (so a cursor on an already-active pill still reads
|
// hot beats `active` (so a cursor on an already-active pill still reads
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ PopupWindow {
|
|||||||
color: Color.popups.background
|
color: Color.popups.background
|
||||||
border.color: Color.popups.border
|
border.color: Color.popups.border
|
||||||
border.width: 2
|
border.width: 2
|
||||||
radius: 0
|
radius: Style.cornerRadius
|
||||||
opacity: root.open ? 1.0 : 0
|
opacity: root.open ? 1.0 : 0
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ Item {
|
|||||||
readonly property string home: Quickshell.env("HOME")
|
readonly property string home: Quickshell.env("HOME")
|
||||||
readonly property string userConfigPath: home + "/.config/omarchy/shell.json"
|
readonly property string userConfigPath: home + "/.config/omarchy/shell.json"
|
||||||
readonly property string defaultsPath: omarchyPath + "/default/quickshell/omarchy-shell/shell-defaults.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 --------------------------------------------------
|
// ---------------- theme --------------------------------------------------
|
||||||
// Bar settings deliberately isn't a themable surface in shell.toml — it
|
// Bar settings deliberately isn't a themable surface in shell.toml — it
|
||||||
@@ -54,22 +53,15 @@ Item {
|
|||||||
property color urgent: Color.urgent
|
property color urgent: Color.urgent
|
||||||
property string fontFamily: "monospace"
|
property string fontFamily: "monospace"
|
||||||
|
|
||||||
// Source-of-truth for the shell-wide corner radius. Mirrors what the menu
|
// Structural style tokens live on the shared Style singleton so toggling
|
||||||
// reads from quickshell-menu.json so `omarchy style corners <sharp|round>`
|
// `omarchy style corners` and theme swaps update every consumer at once.
|
||||||
// flips both surfaces together.
|
// Aliasing them as readonly properties keeps the existing inline component
|
||||||
property int cornerRadius: 0
|
// bindings (`root.cornerRadius`, `root.focusBorderColor`, ...) working
|
||||||
|
// without sprinkling Style.* across the file.
|
||||||
// ---------------- keyboard focus -----------------------------------------
|
readonly property int cornerRadius: Style.cornerRadius
|
||||||
// Keyboard navigation walks the bar form directly; this panel no longer has
|
readonly property color focusBorderColor: Style.focusBorderColor
|
||||||
// side navigation because it only edits the bar.
|
readonly property color focusFillColor: Style.focusFillColor
|
||||||
|
readonly property int focusBorderWidth: Style.focusBorderWidth
|
||||||
// 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
|
|
||||||
|
|
||||||
// Move activeFocus to a dedicated sink Item that lives outside the body
|
// Move activeFocus to a dedicated sink Item that lives outside the body
|
||||||
// tree. Just clearing focus on the previously focused descendant isn't
|
// tree. Just clearing focus on the previously focused descendant isn't
|
||||||
@@ -312,16 +304,6 @@ Item {
|
|||||||
mutateSection(section, function(a) { a[index] = cloneJson(newEntry) })
|
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 -----------------------------------------
|
// ---------------- widget catalog -----------------------------------------
|
||||||
readonly property var legacyWidgetMeta: ({
|
readonly property var legacyWidgetMeta: ({
|
||||||
"omarchy": { name: "Omarchy menu", description: "Launches the Omarchy menu", category: "Compositor" },
|
"omarchy": { name: "Omarchy menu", description: "Launches the Omarchy menu", category: "Compositor" },
|
||||||
@@ -486,14 +468,6 @@ Item {
|
|||||||
onFileChanged: reload()
|
onFileChanged: reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
|
||||||
path: root.styleStatePath
|
|
||||||
watchChanges: true
|
|
||||||
printErrors: false
|
|
||||||
onLoaded: root.loadStyleState(text())
|
|
||||||
onFileChanged: reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------- window -------------------------------------------------
|
// ---------------- window -------------------------------------------------
|
||||||
FloatingWindow {
|
FloatingWindow {
|
||||||
id: window
|
id: window
|
||||||
|
|||||||
Reference in New Issue
Block a user