Rearrange common tokens

This commit is contained in:
Ryan Hughes
2026-05-19 16:06:48 -04:00
parent 6f72604f2c
commit b45795127d
8 changed files with 51 additions and 39 deletions
+16 -14
View File
@@ -14,34 +14,36 @@ active = "{{ color1 }}"
size-horizontal = 26 size-horizontal = 26
size-vertical = 28 size-vertical = 28
[style] [controls]
# Shared control state tokens. See docs/omarchy-shell.md#interactive-states. # Shared state tokens for interactive control chrome (buttons, dropdowns,
# Colors accept palette roles (foreground/accent/urgent/background) or hex. # tab strips, etc).
# Normal: idle control chrome. # Normal: idle control chrome.
normal-color = "foreground" normal-color = "{{ foreground }}"
normal-fill-alpha = 0.04 normal-fill-alpha = 0.04
normal-border-width = 1 normal-border-width = 1
normal-border-alpha = 0.4 normal-border-alpha = 0.4
# Hover-cursor: mouse hover and the panel keyboard cursor. # Hover-cursor: mouse hover and the panel keyboard cursor.
hover-cursor-color = "foreground" hover-cursor-color = "{{ foreground }}"
hover-cursor-fill-alpha = 0.08 hover-cursor-fill-alpha = 0.08
hover-cursor-border-width = 1 hover-cursor-border-width = 1
hover-cursor-border-alpha = 0.25 hover-cursor-border-alpha = 0.25
# Focus: Qt activeFocus. Mirror the hover-cursor values by default so
# mouse hover, keyboard cursor, and tab focus all read as the same state
# — themes that want focus to stand out override these four lines.
focus-color = "{{ foreground }}"
focus-fill-alpha = 0.08
focus-border-width = 1
focus-border-alpha = 0.25
# Selected: persistent chosen/current state. # Selected: persistent chosen/current state.
selected-color = "foreground" selected-color = "{{ foreground }}"
selected-fill-alpha = 0.18 selected-fill-alpha = 0.18
selected-border-width = 0 selected-border-width = 0
selected-border-alpha = 1.0 selected-border-alpha = 1.0
# Focus: Qt activeFocus; inherit hover-cursor unless intentionally different.
focus-color = "hover-cursor"
focus-fill-alpha = "hover-cursor"
focus-border-width = "hover-cursor"
focus-border-alpha = "hover-cursor"
# Momentary fills. # Momentary fills.
pressed-fill-alpha = 0.22 pressed-fill-alpha = 0.22
selection-fill-alpha = 0.35 selection-fill-alpha = 0.35
@@ -72,10 +74,10 @@ base-size = 12
# icon-large = 18 # icon-large = 18
[popups] [popups]
# Shared by every bar flyout. Body text inside flyouts is not separately # Shared by every bar flyout (dropdowns, OSD, popup cards).
# themable — it follows [bar].text.
background = "{{ background }}" background = "{{ background }}"
background-alpha = 1.0 background-alpha = 1.0
text = "{{ foreground }}"
border = "{{ accent }}" border = "{{ accent }}"
border-alpha = 1.0 border-alpha = 1.0
+21 -15
View File
@@ -124,35 +124,37 @@ The shell exposes these tokens to QML via two singletons in
### Interactive states ### Interactive states
`[style]` standardizes reusable control chrome around four states: `[controls]` standardizes reusable control chrome (buttons, dropdowns,
`normal`, `hover-cursor`, `selected`, and `focus`. State colors can be tab strips, etc.) around four states: `normal`, `hover-cursor`, `focus`,
palette roles (`foreground`, `accent`, `urgent`, `background`) or hex and `selected`. State colors accept palette roles (`foreground`,
strings. Fill/border alphas are applied to that state's color. `accent`, `urgent`, `background`) or hex strings; the default template
ships hex values. Fill/border alphas are applied to that state's color.
Focus inherits `hover-cursor` by default so mouse hover, the panel Surfaces like `[menu]`, `[app-launcher]`, and `[image-picker]` define
keyboard cursor, and Qt activeFocus read as the same state. Use the their own `selected-*` tokens and do **not** inherit from `[controls]`.
literal value `"hover-cursor"` on `focus-*` tokens to keep that `[controls]` only governs the shared button/dropdown chrome.
inheritance; set an explicit color/number only when a theme intentionally
wants focus to differ.
| State | Color token | Fill alpha | Border width | Border alpha | | State | Color token | Fill alpha | Border width | Border alpha |
|-------|-------------|------------|--------------|--------------| |-------|-------------|------------|--------------|--------------|
| Normal idle chrome | `normal-color` | `normal-fill-alpha` | `normal-border-width` | `normal-border-alpha` | | Normal idle chrome | `normal-color` | `normal-fill-alpha` | `normal-border-width` | `normal-border-alpha` |
| Hover / keyboard cursor | `hover-cursor-color` | `hover-cursor-fill-alpha` | `hover-cursor-border-width` | `hover-cursor-border-alpha` | | Hover / keyboard cursor | `hover-cursor-color` | `hover-cursor-fill-alpha` | `hover-cursor-border-width` | `hover-cursor-border-alpha` |
| Persistent selected/current | `selected-color` | `selected-fill-alpha` | `selected-border-width` | `selected-border-alpha` |
| Qt activeFocus | `focus-color` | `focus-fill-alpha` | `focus-border-width` | `focus-border-alpha` | | Qt activeFocus | `focus-color` | `focus-fill-alpha` | `focus-border-width` | `focus-border-alpha` |
| Persistent selected/current | `selected-color` | `selected-fill-alpha` | `selected-border-width` | `selected-border-alpha` |
The template ships `focus-*` adjacent to `hover-cursor-*` with the same
values so mouse hover, keyboard cursor, and tab focus read identically.
Themes that want focus to stand out override the four `focus-*` keys.
Border widths are the theme-level on/off switches for state borders; set Border widths are the theme-level on/off switches for state borders; set
a width to `0` to keep the fill while removing that state border. The a width to `0` to keep the fill while removing that state border. The
default theme keeps selected borders off globally (`selected-border-width default keeps selected borders off globally (`selected-border-width =
= 0`); explicitly bordered controls can still keep their normal border 0`); explicitly bordered controls keep their normal border when selected.
when selected.
```toml ```toml
[style] [controls]
# Accent-tinted cursor/focus, foreground-tinted selected state. # Accent-tinted cursor/focus, foreground-tinted selected state.
hover-cursor-color = "accent" hover-cursor-color = "accent"
focus-color = "hover-cursor" focus-color = "accent"
selected-color = "foreground" selected-color = "foreground"
# Keep selected fills but remove selected-state borders. # Keep selected fills but remove selected-state borders.
@@ -164,6 +166,10 @@ Momentary fills use `pressed-fill-alpha` for button press feedback and
`pressed-color` or `selection-color`; they fall back to hover-cursor and `pressed-color` or `selection-color`; they fall back to hover-cursor and
foreground respectively. foreground respectively.
The section was previously named `[style]`. Hand-written theme
`shell.toml` files using the old name still apply — the parser accepts
both `[controls]` and `[style]`.
### Spacing ### Spacing
`[spacing] scale` multiplies the shell's shared margins, gaps, and `[spacing] scale` multiplies the shell's shared margins, gaps, and
+1
View File
@@ -65,6 +65,7 @@ QtObject {
} }
readonly property QtObject popups: QtObject { readonly property QtObject popups: QtObject {
property color background: root.composed("popups.background", "popups.background-alpha", root.background, 1.0) property color background: root.composed("popups.background", "popups.background-alpha", root.background, 1.0)
property color text: root.pick("popups.text", root.foreground)
property color border: root.composed("popups.border", "popups.border-alpha", root.pick("notifications.border", root.accent), 1.0) property color border: root.composed("popups.border", "popups.border-alpha", root.pick("notifications.border", root.accent), 1.0)
} }
readonly property QtObject tooltip: QtObject { readonly property QtObject tooltip: QtObject {
+7 -4
View File
@@ -372,10 +372,10 @@ QtObject {
} }
// Parse [font] base-size + per-token overrides, [bar] size-* keys, // Parse [font] base-size + per-token overrides, [bar] size-* keys,
// [style] state colors / alphas / border widths, and [spacing] scale + // [controls] state colors / alphas / border widths, and [spacing] scale +
// token overrides out of shell.toml. Color.qml owns the quoted-string // token overrides out of shell.toml. Color.qml owns the quoted-string
// side of the surface color sections; Style owns quoted strings only // side of the surface color sections; Style owns quoted strings only
// inside [style]. // inside [controls].
function loadShell(raw) { function loadShell(raw) {
var fontOut = {} var fontOut = {}
var barOut = {} var barOut = {}
@@ -393,7 +393,7 @@ QtObject {
var sectionMatch = line.match(/^\[([A-Za-z0-9_-]+)\]\s*(#.*)?$/) var sectionMatch = line.match(/^\[([A-Za-z0-9_-]+)\]\s*(#.*)?$/)
if (sectionMatch) { section = sectionMatch[1]; continue } if (sectionMatch) { section = sectionMatch[1]; continue }
// Accept ints/floats for numeric tokens and quoted/bare words for // Accept ints/floats for numeric tokens and quoted/bare words for
// [style] color roles / inheritance sentinels (e.g. "foreground", // [controls] color roles / inheritance sentinels (e.g. "foreground",
// "accent", "hover-cursor", "#c0caf5"). // "accent", "hover-cursor", "#c0caf5").
var numKv = line.match(/^([A-Za-z0-9_-]+)\s*=\s*(-?\d+(?:\.\d+)?)\s*(#.*)?$/) var numKv = line.match(/^([A-Za-z0-9_-]+)\s*=\s*(-?\d+(?:\.\d+)?)\s*(#.*)?$/)
var stringKv = line.match(/^([A-Za-z0-9_-]+)\s*=\s*["']([^"']+)["']\s*(#.*)?$/) var stringKv = line.match(/^([A-Za-z0-9_-]+)\s*=\s*["']([^"']+)["']\s*(#.*)?$/)
@@ -412,7 +412,10 @@ QtObject {
var fval = parseFloat(rawValue) var fval = parseFloat(rawValue)
if (key === "scale") nextSpacingScale = fval if (key === "scale") nextSpacingScale = fval
else spacingOut[key] = fval else spacingOut[key] = fval
} else if (section === "style") { } else if (section === "controls" || section === "style") {
// `[controls]` is the canonical section name; `[style]` is kept
// as a legacy alias so hand-written theme shell.toml files that
// predate the rename still apply.
styleOut[key] = numKv ? parseFloat(rawValue) : rawValue styleOut[key] = numKv ? parseFloat(rawValue) : rawValue
} }
} }
+1 -1
View File
@@ -13,7 +13,7 @@ import qs.Commons
// idle transparent or normal border if `bordered` // idle transparent or normal border if `bordered`
// //
// All fills/borders come from `qs.Commons.Style` tokens, so themes // All fills/borders come from `qs.Commons.Style` tokens, so themes
// control the look via [style] in shell.toml. // control the look via [controls] in shell.toml.
// //
// Emits `hovered(bool)` so panels with their own keyboard cursor model // Emits `hovered(bool)` so panels with their own keyboard cursor model
// can update state on mouse enter/leave. // can update state on mouse enter/leave.
+1 -1
View File
@@ -22,7 +22,7 @@ Item {
property string value: "" property string value: ""
property var options: [] property var options: []
property color foreground: Color.foreground property color foreground: Color.popups.text
property color background: Color.popups.background property color background: Color.popups.background
property color popupBorder: Color.popups.border property color popupBorder: Color.popups.border
property color accent: Color.accent property color accent: Color.accent
+1 -1
View File
@@ -25,7 +25,7 @@ Item {
property string emptyText: "No matches" property string emptyText: "No matches"
property string triggerLabel: "" property string triggerLabel: ""
property color foreground: Color.foreground property color foreground: Color.popups.text
property color background: Color.popups.background property color background: Color.popups.background
property color popupBorder: Color.popups.border property color popupBorder: Color.popups.border
property color accent: Color.accent property color accent: Color.accent
+3 -3
View File
@@ -107,14 +107,14 @@ Item {
text: root.icon text: root.icon
font.family: Style.font.family font.family: Style.font.family
font.pixelSize: Style.font.displayLarge font.pixelSize: Style.font.displayLarge
color: Color.foreground color: Color.popups.text
} }
Rectangle { Rectangle {
visible: root.hasProgress visible: root.hasProgress
width: visible ? Style.space(142) : 0 width: visible ? Style.space(142) : 0
height: Math.max(Style.space(6), Style.spacing.sm) height: Math.max(Style.space(6), Style.spacing.sm)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: Color.alpha(Color.foreground, 0.45) color: Color.alpha(Color.popups.text, 0.45)
Rectangle { Rectangle {
height: parent.height height: parent.height
width: parent.width * (root.hasProgress ? root.value / root.maxValue : 0) width: parent.width * (root.hasProgress ? root.value / root.maxValue : 0)
@@ -128,7 +128,7 @@ Item {
font.family: Style.font.family font.family: Style.font.family
font.bold: true font.bold: true
font.pixelSize: Style.font.title font.pixelSize: Style.font.title
color: Color.foreground color: Color.popups.text
elide: Text.ElideRight elide: Text.ElideRight
maximumLineCount: 1 maximumLineCount: 1
clip: true clip: true