How the Interactive State System ([controls]) Works in Omarchy Themes
The [controls] section in Omarchy’s TOML-based theme system defines a unified token set for interactive UI elements, enabling consistent styling of buttons, dropdowns, and focus states through shallow-merged configuration files that update at runtime.
Omarchy’s theming engine relies on a token-based architecture where colors.toml files drive the visual appearance of the desktop environment. The interactive state system, exposed via the [controls] section, centralizes styling for all clickable and focusable chrome components according to the basecamp/omarchy source code.
What Is the [controls] Interactive State System?
The [controls] section acts as a dedicated namespace within Omarchy’s theme configuration. It isolates visual properties for interactive "chrome"—buttons, dropdown arrows, text input fields, and selection highlights—from the generic appearance tokens defined in [style].
Token Scope and Purpose
According to docs/theming.md at line 275, [controls] governs shared controls such as buttons, dropdowns, and text fields【/__modal/volumes/vo-cSqLfqnnIwYXEonuEJnnZa/repos/github.com/basecamp/omarchy/quattro/docs/theming.md#L275】. The system exposes state-specific tokens including:
bgandfg– default background and foreground colorshover-bgandhover-fg– mouse-over statesselected-bgandselected-fg– active or highlighted statesdisabled-bganddisabled-fg– non-interactive statesborderandradius– structural dimensions
These tokens ensure that every interactive element shares a cohesive visual language across the shell.
Configuration Structure
Each theme stores its [controls] definition inside a colors.toml file. The default theme provides baseline values, while user-customized themes override specific tokens without replacing the entire set. This shallow-merge behavior means undefined tokens inherit from the parent theme, while explicitly declared values take precedence.
How [controls] Tokens Are Resolved at Runtime
Omarchy’s shell does not hardcode colors. Instead, it queries a theme manager that resolves token names like controls.bg or controls.selected-fg against the active configuration.
Theme Merging and Inheritance
The inheritance model follows a strict hierarchy:
- Default theme loads first, populating the token map with baseline
[controls]values. - User theme (e.g.,
~/.config/omarchy/themes/custom/colors.toml) loads second, shallow-merging its[controls]section into the default map. - Runtime resolution occurs when QML widgets request
Theme.controls.hover-bgor similar properties.
As documented in docs/omarchy-shell.md at lines 220-229, this system standardizes reusable control chrome and only governs the shared button/dropdown chrome【/__modal/volumes/vo-cSqLfqnnIwYXEonuEJnnZa/repos/github.com/basecamp/omarchy/quattro/docs/omarchy-shell.md#L220】, leaving application-specific styling untouched.
QML Integration and Dynamic Updates
Widgets written in QML access [controls] tokens through the Theme or OmarchyTheme helper objects. When the user switches themes via the CLI command omarchy theme set <name>, the theme manager reloads the TOML files, recomputes the merged token map, and emits change notifications. All bound QML properties update instantly, triggering a seamless visual transition without restarting the shell.
Practical Implementation Examples
Customizing Control States in colors.toml
Create or edit a user theme file to override specific interactive states:
# ~/.config/omarchy/themes/nord-custom/colors.toml
[controls]
bg = "#2e3440"
fg = "#d8dee9"
hover-bg = "#3b4252"
hover-fg = "#eceff4"
selected-bg = "#88c0d0"
selected-fg = "#2e3440"
disabled-bg = "#4c566a"
disabled-fg = "#d8dee9"
radius = "6px"
Only the tokens defined here replace the defaults; all other [controls] values inherit from the parent theme.
Consuming Tokens in QML Widgets
Reference the tokens in widget code to ensure consistent styling:
// Example button implementation in a panel widget
Rectangle {
id: controlButton
width: 120
height: 32
radius: Theme.controls.radius
color: Theme.controls.bg
Text {
anchors.centerIn: parent
text: "Submit"
color: Theme.controls.fg
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: controlButton.color = Theme.controls.hover-bg
onExited: controlButton.color = Theme.controls.bg
onPressed: controlButton.color = Theme.controls.selected-bg
}
}
The Theme.controls object resolves to the merged [controls] section from the active theme configuration.
Switching Themes via CLI
Activate a different theme to instantly swap [controls] values across the entire shell:
# Switch to the tokyo-night theme which includes its own [controls] definition
omarchy theme set tokyo-night
The shell references config/omarchy/shell.json to locate the theme directory, reloads the TOML, and reapplies all control states without requiring a session restart.
Summary
- The
[controls]section incolors.tomlfiles defines the interactive state system for Omarchy themes, separating button and dropdown styling from generic[style]tokens. - Token inheritance uses a shallow-merge strategy, allowing users to override specific states (
hover-bg,selected-fg, etc.) while retaining default values for unspecified properties. - The theme manager resolves tokens at runtime through
Theme.controlsaccessors, enabling QML widgets to bind directly to configuration values. - Source documentation in
docs/theming.md(line 275) anddocs/omarchy-shell.md(lines 220-229) explicitly defines[controls]as the governing system for shared interactive chrome. - Theme switches propagate instantly to all UI components, providing a dynamic, configuration-driven desktop environment.
Frequently Asked Questions
What file format does Omarchy use for the [controls] interactive state system?
Omarchy uses TOML files named colors.toml located within individual theme directories (e.g., themes/tokyo-night/colors.toml or ~/.config/omarchy/themes/custom/colors.toml). The [controls] header within these files groups the interactive state tokens separately from [style] or [accent] sections.
How do I override default [controls] tokens without breaking existing themes?
Override tokens by creating a user-specific theme directory and defining only the keys you wish to change inside [controls]. The system performs a shallow merge, so any token you omit continues to inherit from the default theme loaded from the base installation.
Do [controls] tokens affect non-interactive UI elements?
No. According to the source documentation, [controls] only governs the shared button/dropdown chrome and explicitly excludes generic window backgrounds, text content, or decorative elements. Those properties reside under the [style] section or other specialized token groups.
Can I animate [controls] state changes in QML?
Yes. Because QML properties bind to Theme.controls values, you can apply standard QML animation behaviors (such as Behavior on color { ColorAnimation { duration: 150 } }) to properties driven by [controls] tokens. The theme system provides the values; the widget implementation handles the interpolation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →