From 201a0035374b6bea86630532143580a540723cdc Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Tue, 19 May 2026 16:55:54 -0400 Subject: [PATCH] More tokens --- default/themed/shell.toml.tpl | 60 +++++++++++++++---- docs/omarchy-shell.md | 3 +- shell/Commons/Color.qml | 32 ++++++++-- shell/plugins/app-launcher/AppLauncher.qml | 3 +- .../clipboard-picker/ClipboardPicker.qml | 22 ++++--- shell/plugins/emoji-picker/EmojiPicker.qml | 20 ++++--- shell/plugins/image-picker/ImagePicker.qml | 3 +- shell/plugins/lock/LockView.qml | 12 ++-- shell/plugins/menu/Menu.qml | 5 +- shell/plugins/polkit/PolkitAgent.qml | 25 ++++---- shell/plugins/settings/SettingsPanel.qml | 4 +- .../plugins/settings/components/NDropdown.qml | 4 +- 12 files changed, 136 insertions(+), 57 deletions(-) diff --git a/default/themed/shell.toml.tpl b/default/themed/shell.toml.tpl index 5d8e58ba..e1ffb521 100644 --- a/default/themed/shell.toml.tpl +++ b/default/themed/shell.toml.tpl @@ -101,15 +101,16 @@ countdown = "{{ accent }}" [app-launcher] # Same six tokens as [menu], applied to the app launcher overlay. Alpha -# companions go from 0 (invisible) to 1 (opaque). Defaults mirror [menu]: -# subtle foreground-tinted fill on the selected row, no visible border, -# accent-colored text. background-alpha of 0.95 mirrors the legacy -# hard-coded card translucency. +# companions go from 0 (invisible) to 1 (opaque). scrim is the full-screen +# dim layer behind the card; background is the card itself. Defaults +# mirror [menu] with the card at 0.95 to preserve the legacy translucency. background = "{{ background }}" background-alpha = 0.95 text = "{{ foreground }}" border = "{{ foreground }}" border-alpha = 1.0 +scrim = "{{ background }}" +scrim-alpha = 0.5 selected-background = "{{ foreground }}" selected-background-alpha = 0.08 selected-text = "{{ accent }}" @@ -118,26 +119,63 @@ selected-border-alpha = 0.25 [menu] # Cards, rows, and selected-row treatment. Alpha companions (where present) -# go from 0 (invisible) to 1 (opaque). Defaults mirror the panel keyboard -# cursor: a subtle foreground-tinted fill on the selected row, no visible -# border, accent-colored text. Override any of these per-theme. +# go from 0 (invisible) to 1 (opaque). scrim is the full-screen dim layer +# behind the card. The clipboard and emoji pickers inherit these tokens. background = "{{ background }}" background-alpha = 1.0 text = "{{ foreground }}" border = "{{ foreground }}" border-alpha = 1.0 +scrim = "{{ background }}" +scrim-alpha = 0.5 selected-background = "{{ foreground }}" selected-background-alpha = 0.08 selected-text = "{{ accent }}" selected-border = "{{ foreground }}" selected-border-alpha = 0.25 +[polkit] +# Polkit authentication prompt (sudo/password dialogs). scrim is the +# darkening layer behind the card; background is the card itself. +# text-error tints the lock icon, password text, and placeholder when +# authentication fails. +background = "{{ background }}" +background-alpha = 1.0 +text = "{{ foreground }}" +text-error = "{{ color1 }}" +border = "{{ accent }}" +border-error = "{{ color1 }}" +border-alpha = 1.0 +scrim = "{{ background }}" +scrim-alpha = 0.5 +# accent is the lock-icon glyph color + text-selection tint. +accent = "{{ accent }}" + +[lock] +# Lock screen password input. background/background-alpha control the +# centered input field card; border/border-active/border-error cycle +# through idle, typing/authenticating, and wrong-password states. +background = "{{ background }}" +background-alpha = 0.8 +text = "{{ foreground }}" +text-error = "{{ color1 }}" +border = "{{ foreground }}" +border-active = "{{ accent }}" +border-error = "{{ color1 }}" +border-alpha = 1.0 +# selection is the text-selection tint inside the input field. +selection = "{{ accent }}" +selection-alpha = 0.45 + [image-picker] -# Carousel-style picker. background-alpha sets the scrim opacity behind -# the picker; unselected-border-alpha softens carousel slices that aren't -# the current selection. Defaults preserve the legacy hard-coded behavior. +# Carousel-style picker. The picker has no separate card surface, so +# `scrim` is the full-screen wash. `background` is the underlying color +# used for per-slice dim overlays and text outlines on top of the scrim. +# unselected-border-alpha softens carousel slices that aren't selected. background = "{{ background }}" -background-alpha = 0.5 +background-alpha = 1.0 +scrim = "{{ background }}" +scrim-alpha = 0.5 text = "{{ foreground }}" selected-border = "{{ accent }}" selected-border-alpha = 1.0 diff --git a/docs/omarchy-shell.md b/docs/omarchy-shell.md index 27d62a8e..5191472f 100644 --- a/docs/omarchy-shell.md +++ b/docs/omarchy-shell.md @@ -116,7 +116,8 @@ The shell exposes these tokens to QML via two singletons in - `Color` — palette (`foreground`, `background`, `accent`, `urgent`) and per-surface roles (`Color.bar.*`, `Color.popups.*`, `Color.tooltip.*`, `Color.notifications.*`, `Color.menu.*`, - `Color.imagePicker.*`). + `Color.appLauncher.*`, `Color.imagePicker.*`, `Color.polkit.*`, + `Color.lock.*`). The clipboard and emoji pickers share `Color.menu.*`. - `Style` — structural tokens (`cornerRadius`), shared interactive state tokens/helpers, spacing (`Style.spacing.*` / `Style.space(px)`), the type scale (`Style.font.*`), and bar dimensions diff --git a/shell/Commons/Color.qml b/shell/Commons/Color.qml index fb02ecfc..a3b904fb 100644 --- a/shell/Commons/Color.qml +++ b/shell/Commons/Color.qml @@ -7,7 +7,8 @@ import Quickshell.Io // (foreground/background/accent/urgent) come from the theme's colors.toml. // Per-surface roles (Color.bar.*, Color.popups.*, Color.tooltip.*, // Color.notifications.*, Color.menu.*, Color.appLauncher.*, -// Color.imagePicker.*) come from shell.toml, which is generated +// Color.imagePicker.*, Color.polkit.*, Color.lock.*) come from shell.toml, +// which is generated // per theme from default/themed/shell.toml.tpl (or shipped directly by a // theme to override). Surfaces that don't appear in shell.toml fall back to // the foundational palette, so themes can ship partial overrides. @@ -85,6 +86,7 @@ QtObject { property color background: root.composed("app-launcher.background", "app-launcher.background-alpha", root.background, 0.95) property color text: root.pick("app-launcher.text", root.foreground) property color border: root.composed("app-launcher.border", "app-launcher.border-alpha", root.foreground, 1.0) + property color scrim: root.composed("app-launcher.scrim", "app-launcher.scrim-alpha", root.background, 0.5) property color selectedBackground: root.composed("app-launcher.selected-background", "app-launcher.selected-background-alpha", root.foreground, 0.08) property color selectedText: root.pick("app-launcher.selected-text", root.accent) property color selectedBorder: root.composed("app-launcher.selected-border", "app-launcher.selected-border-alpha", root.foreground, 0.0) @@ -96,15 +98,35 @@ QtObject { property color background: root.composed("menu.background", "menu.background-alpha", root.background, 1.0) property color text: root.pick("menu.text", root.foreground) property color border: root.composed("menu.border", "menu.border-alpha", root.foreground, 1.0) + property color scrim: root.composed("menu.scrim", "menu.scrim-alpha", root.background, 0.5) property color selectedBackground: root.composed("menu.selected-background", "menu.selected-background-alpha", root.pick("menu.selected", root.foreground), 0.08) property color selectedText: root.pick("menu.selected-text", root.accent) property color selectedBorder: root.composed("menu.selected-border", "menu.selected-border-alpha", root.foreground, 0.0) } + readonly property QtObject polkit: QtObject { + property color background: root.composed("polkit.background", "polkit.background-alpha", root.background, 1.0) + property color text: root.pick("polkit.text", root.foreground) + property color textError: root.pick("polkit.text-error", root.urgent) + property color border: root.composed("polkit.border", "polkit.border-alpha", root.accent, 1.0) + property color borderError: root.composed("polkit.border-error", "polkit.border-alpha", root.urgent, 1.0) + property color accent: root.pick("polkit.accent", root.accent) + property color scrim: root.composed("polkit.scrim", "polkit.scrim-alpha", root.background, 0.5) + } + readonly property QtObject lock: QtObject { + property color background: root.composed("lock.background", "lock.background-alpha", root.background, 0.8) + property color text: root.pick("lock.text", root.foreground) + property color textError: root.pick("lock.text-error", root.urgent) + property color border: root.composed("lock.border", "lock.border-alpha", root.foreground, 1.0) + property color borderActive: root.composed("lock.border-active", "lock.border-alpha", root.accent, 1.0) + property color borderError: root.composed("lock.border-error", "lock.border-alpha", root.urgent, 1.0) + property color selection: root.composed("lock.selection", "lock.selection-alpha", root.accent, 0.45) + } readonly property QtObject imagePicker: QtObject { - // Defaults reflect what the picker hard-coded before alphas were - // themable: scrim background at 0.5, unselected carousel borders at - // 0.28, selected border fully opaque. - property color background: root.composed("image-picker.background", "image-picker.background-alpha", root.background, 0.5) + // The picker has no separate card; `scrim` is the full-screen dim + // wash, `background` is the palette color used for per-slice dim + // overlays and text outlines on top of the scrim. + property color background: root.composed("image-picker.background", "image-picker.background-alpha", root.background, 1.0) + property color scrim: root.composed("image-picker.scrim", "image-picker.scrim-alpha", root.background, 0.5) property color text: root.pick("image-picker.text", root.foreground) property color selectedBorder: root.composed("image-picker.selected-border", "image-picker.selected-border-alpha", root.accent, 1.0) property color unselectedBorder: root.composed("image-picker.unselected-border", "image-picker.unselected-border-alpha", root.foreground, 0.28) diff --git a/shell/plugins/app-launcher/AppLauncher.qml b/shell/plugins/app-launcher/AppLauncher.qml index c79fc19c..1022340e 100644 --- a/shell/plugins/app-launcher/AppLauncher.qml +++ b/shell/plugins/app-launcher/AppLauncher.qml @@ -32,6 +32,7 @@ Item { property color background: Color.appLauncher.background property color foreground: Color.appLauncher.text property color border: Color.appLauncher.border + property color scrim: Color.appLauncher.scrim property color selectedBackground: Color.appLauncher.selectedBackground property color selectedText: Color.appLauncher.selectedText property color selectedBorder: Color.appLauncher.selectedBorder @@ -336,7 +337,7 @@ Item { Rectangle { anchors.fill: parent - color: root.withAlpha(root.background, 0.5) + color: root.scrim } MouseArea { diff --git a/shell/plugins/clipboard-picker/ClipboardPicker.qml b/shell/plugins/clipboard-picker/ClipboardPicker.qml index faa7c339..eb25d512 100644 --- a/shell/plugins/clipboard-picker/ClipboardPicker.qml +++ b/shell/plugins/clipboard-picker/ClipboardPicker.qml @@ -16,10 +16,16 @@ Item { property string historyPath: Quickshell.env("HOME") + "/.local/state/omarchy/clipboard-history.json" property string captureScript: root.omarchyPath + "/shell/scripts/clipboard-capture.sh" - property color accent: Color.menu.selected + // Shares the [menu] surface tokens — themes that style the menu also + // style the clipboard picker. Selected-row colors composed in the + // singleton so consumers drop them straight into Rectangle bindings. property color background: Color.menu.background property color foreground: Color.menu.text - property color border: foreground + property color border: Color.menu.border + property color scrim: Color.menu.scrim + property color selectedBackground: Color.menu.selectedBackground + property color selectedText: Color.menu.selectedText + property color selectedBorder: Color.menu.selectedBorder readonly property int cornerRadius: Style.cornerRadius property string fontFamily: Quickshell.env("OMARCHY_MENU_FONT") || "monospace" property int contentMargin: Style.spacing.panelPadding @@ -254,7 +260,7 @@ Item { Rectangle { anchors.fill: parent - color: root.withAlpha(root.background, 0.5) + color: root.scrim } MouseArea { @@ -365,9 +371,9 @@ Item { width: ListView.view.width height: root.rowHeight radius: root.cornerRadius - color: hasCursor ? Style.hoverFillFor(root.foreground, root.accent) : "transparent" - border.color: hasCursor ? Style.hoverBorderFor(root.foreground, root.accent) : "transparent" - border.width: hasCursor ? Style.hoverBorderWidth : 0 + color: hasCursor ? root.selectedBackground : "transparent" + border.color: hasCursor ? root.selectedBorder : "transparent" + border.width: (hasCursor && root.selectedBorder.a > 0) ? Style.hoverBorderWidth : 0 Row { anchors.fill: parent @@ -391,7 +397,7 @@ Item { width: parent.width - (parent.parent.entryType === "image" ? parent.height + parent.spacing : 0) height: parent.height text: parent.parent.previewText - color: parent.parent.hasCursor ? Style.hoverStateColor(root.foreground, root.accent) : root.foreground + color: parent.parent.hasCursor ? root.selectedText : root.foreground font.family: root.fontFamily font.pixelSize: Style.font.title font.italic: parent.parent.entryType === "image" @@ -462,7 +468,7 @@ Item { Text { text: "󰅌" - color: root.accent + color: root.selectedText opacity: 0.8 font.family: root.fontFamily font.pixelSize: Style.font.displayLarge diff --git a/shell/plugins/emoji-picker/EmojiPicker.qml b/shell/plugins/emoji-picker/EmojiPicker.qml index 136c25a5..7af59bac 100644 --- a/shell/plugins/emoji-picker/EmojiPicker.qml +++ b/shell/plugins/emoji-picker/EmojiPicker.qml @@ -18,10 +18,16 @@ Item { property var emojis: [] property var filteredEmojis: [] - property color accent: Color.menu.selected + // Shares the [menu] surface tokens — themes that style the menu also + // style the emoji picker. Selected-cell colors composed in the + // singleton so consumers drop them straight into Rectangle bindings. property color background: Color.menu.background property color foreground: Color.menu.text - property color border: foreground + property color border: Color.menu.border + property color scrim: Color.menu.scrim + property color selectedBackground: Color.menu.selectedBackground + property color selectedText: Color.menu.selectedText + property color selectedBorder: Color.menu.selectedBorder readonly property int cornerRadius: Style.cornerRadius property string fontFamily: Quickshell.env("OMARCHY_MENU_FONT") || "monospace" property int contentMargin: Style.spacing.panelPadding @@ -178,7 +184,7 @@ Item { Rectangle { anchors.fill: parent - color: root.withAlpha(root.background, 0.5) + color: root.scrim } MouseArea { @@ -288,9 +294,9 @@ Item { width: root.cellWidth height: root.cellHeight radius: root.cornerRadius - color: hasCursor ? Style.hoverFillFor(root.foreground, root.accent) : "transparent" - border.color: hasCursor ? Style.hoverBorderFor(root.foreground, root.accent) : "transparent" - border.width: hasCursor ? Style.hoverBorderWidth : 0 + color: hasCursor ? root.selectedBackground : "transparent" + border.color: hasCursor ? root.selectedBorder : "transparent" + border.width: (hasCursor && root.selectedBorder.a > 0) ? Style.hoverBorderWidth : 0 Text { text: parent.emoji @@ -326,7 +332,7 @@ Item { Text { text: "󰈉" - color: root.accent + color: root.selectedText opacity: 0.8 font.family: root.fontFamily font.pixelSize: Style.font.displayLarge diff --git a/shell/plugins/image-picker/ImagePicker.qml b/shell/plugins/image-picker/ImagePicker.qml index 37f9a49d..5f4f232d 100644 --- a/shell/plugins/image-picker/ImagePicker.qml +++ b/shell/plugins/image-picker/ImagePicker.qml @@ -31,6 +31,7 @@ Item { // Bound to the central [image-picker] section in shell.toml via Color.qml. property color background: Color.imagePicker.background property color foreground: Color.imagePicker.text + property color scrim: Color.imagePicker.scrim property color selectedBorder: Color.imagePicker.selectedBorder property color unselectedBorder: Color.imagePicker.unselectedBorder property int expandedWidth: 768 @@ -440,7 +441,7 @@ Item { Rectangle { anchors.fill: parent visible: root.opened && root.imagesLoaded - color: root.background + color: root.scrim } MouseArea { diff --git a/shell/plugins/lock/LockView.qml b/shell/plugins/lock/LockView.qml index 085ada9b..54d14c84 100644 --- a/shell/plugins/lock/LockView.qml +++ b/shell/plugins/lock/LockView.qml @@ -87,8 +87,8 @@ Item { width: root.fieldWidth height: root.fieldHeight anchors.centerIn: parent - color: root.withAlpha(Color.background, 0.8) - border.color: root.failureMessage.length > 0 ? Color.urgent : (root.authenticatingPassword ? Color.accent : Color.foreground) + color: Color.lock.background + border.color: root.failureMessage.length > 0 ? Color.lock.borderError : (root.authenticatingPassword ? Color.lock.borderActive : Color.lock.border) border.width: root.outlineThickness radius: Style.cornerRadius clip: true @@ -107,9 +107,9 @@ Item { echoMode: TextInput.Password passwordCharacter: "\u2022" passwordMaskDelay: 0 - color: Color.foreground - selectionColor: root.withAlpha(Color.accent, 0.45) - selectedTextColor: Color.foreground + color: Color.lock.text + selectionColor: Color.lock.selection + selectedTextColor: Color.lock.text font.family: "monospace" font.pixelSize: root.fieldFontSize cursorVisible: activeFocus && !root.authenticatingPassword && root.hasTyped @@ -139,7 +139,7 @@ Item { anchors.fill: passwordInput text: root.failureMessage.length > 0 ? root.failureMessage : root.placeholderText visible: passwordInput.text.length === 0 - color: root.failureMessage.length > 0 ? Color.urgent : Color.foreground + color: root.failureMessage.length > 0 ? Color.lock.textError : Color.lock.text font.family: "monospace" font.pixelSize: root.fieldFontSize font.italic: root.failureMessage.length > 0 diff --git a/shell/plugins/menu/Menu.qml b/shell/plugins/menu/Menu.qml index 012e511f..097e7010 100644 --- a/shell/plugins/menu/Menu.qml +++ b/shell/plugins/menu/Menu.qml @@ -68,6 +68,7 @@ Item { property color background: Color.menu.background property color foreground: Color.menu.text property color border: Color.menu.border + property color scrim: Color.menu.scrim property color selectedBackground: Color.menu.selectedBackground property color selectedText: Color.menu.selectedText property color selectedBorder: Color.menu.selectedBorder @@ -942,7 +943,7 @@ Item { Rectangle { anchors.fill: parent - color: root.withAlpha(root.background, 0.5) + color: root.scrim } MouseArea { @@ -1194,7 +1195,7 @@ Item { Text { text: "󰈉" - color: root.selectedBackground + color: root.selectedText opacity: 0.8 font.family: root.fontFamily font.pixelSize: Style.font.displayLarge diff --git a/shell/plugins/polkit/PolkitAgent.qml b/shell/plugins/polkit/PolkitAgent.qml index 342a0aad..39efa507 100644 --- a/shell/plugins/polkit/PolkitAgent.qml +++ b/shell/plugins/polkit/PolkitAgent.qml @@ -9,10 +9,13 @@ Item { id: root property string fontFamily: Quickshell.env("OMARCHY_MENU_FONT") || "monospace" - property color accent: Color.accent - property color background: Color.menu.background - property color foreground: Color.menu.text - property color border: foreground + // Bound to the central [polkit] section in shell.toml via Color.qml. + property color accent: Color.polkit.accent + property color background: Color.polkit.background + property color foreground: Color.polkit.text + property color border: Color.polkit.border + property color borderError: Color.polkit.borderError + property color scrim: Color.polkit.scrim readonly property int cornerRadius: Style.cornerRadius property int contentMargin: Style.spacing.panelPadding property int fieldHeight: Math.max(Style.space(42), Style.spacing.controlHeight) @@ -212,7 +215,7 @@ Item { Rectangle { anchors.fill: parent - color: root.withAlpha(root.background, 0.5) + color: root.scrim } MouseArea { @@ -228,7 +231,7 @@ Item { anchors.centerIn: parent anchors.horizontalCenterOffset: root.shakeOffset color: root.background - border.color: root.accent + border.color: root.errorFlash ? root.borderError : root.border border.width: Math.max(1, Style.space(2)) MouseArea { anchors.fill: parent; onClicked: root.refocus() } @@ -258,7 +261,7 @@ Item { Text { text: "\uf023" - color: root.errorFlash ? Color.urgent : root.accent + color: root.errorFlash ? Color.polkit.textError : root.accent font.family: root.fontFamily font.pixelSize: Style.font.iconLarge width: Style.space(26) @@ -277,13 +280,13 @@ Item { verticalAlignment: TextInput.AlignVCenter activeFocusOnPress: true clip: true - selectionColor: root.withAlpha(root.accent, 0.45) + selectionColor: Color.alpha(root.accent, 0.45) selectedTextColor: root.foreground font.family: root.fontFamily font.pixelSize: Style.font.iconLarge echoMode: root.responseVisible ? TextInput.Normal : TextInput.Password passwordCharacter: "\u2022" - color: root.errorFlash ? Color.urgent : root.foreground + color: root.errorFlash ? Color.polkit.textError : root.foreground cursorVisible: activeFocus && !root.submitted && !root.errorFlash readOnly: root.submitted || root.errorFlash enabled: root.dialogVisible && !root.fingerprintWaiting @@ -302,7 +305,7 @@ Item { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter text: root.errorFlash ? "Wrong" : (root.submitted ? "Checking..." : "Enter password") - color: root.errorFlash ? Color.urgent : root.foreground + color: root.errorFlash ? Color.polkit.textError : root.foreground opacity: root.errorFlash ? 1 : 0.36 font.family: root.fontFamily font.pixelSize: Style.font.iconLarge @@ -315,7 +318,7 @@ Item { height: Style.space(24) anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter - color: root.errorFlash ? Color.urgent : root.foreground + color: root.errorFlash ? Color.polkit.textError : root.foreground visible: passwordInput.visible && passwordInput.activeFocus && passwordInput.text.length === 0 && !root.submitted && !root.errorFlash } diff --git a/shell/plugins/settings/SettingsPanel.qml b/shell/plugins/settings/SettingsPanel.qml index eee1b769..2a962255 100644 --- a/shell/plugins/settings/SettingsPanel.qml +++ b/shell/plugins/settings/SettingsPanel.qml @@ -41,8 +41,8 @@ Item { // ---------------- theme -------------------------------------------------- // Bar settings deliberately isn't a themable surface in shell.toml — it // tracks the foundational palette so every theme renders consistently. - property color foreground: Color.foreground - property color background: Color.background + property color foreground: Color.popups.text + property color background: Color.popups.background property color accent: Color.accent property color urgent: Color.urgent property string fontFamily: "monospace" diff --git a/shell/plugins/settings/components/NDropdown.qml b/shell/plugins/settings/components/NDropdown.qml index aebb837d..5a2e4242 100644 --- a/shell/plugins/settings/components/NDropdown.qml +++ b/shell/plugins/settings/components/NDropdown.qml @@ -11,8 +11,8 @@ Item { property string label: "" property string value: "" property var options: [] - property color foreground: Color.foreground - property color background: Color.background + property color foreground: Color.popups.text + property color background: Color.popups.background property color accent: Color.accent property string fontFamily: Style.font.family property int cornerRadius: 0