# How the Interactive State System ([controls]) Works in Omarchy Themes

> Learn how Omarchy themes use the [controls] system for consistent interactive UI styling. Discover runtime updates and unified token sets for buttons, dropdowns, and focus states.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: internals
- Published: 2026-08-28

---

**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`](https://github.com/basecamp/omarchy/blob/main/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`](https://github.com/basecamp/omarchy/blob/main/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:

- `bg` and `fg` – default background and foreground colors
- `hover-bg` and `hover-fg` – mouse-over states
- `selected-bg` and `selected-fg` – active or highlighted states
- `disabled-bg` and `disabled-fg` – non-interactive states
- `border` and `radius` – 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`](https://github.com/basecamp/omarchy/blob/main/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:

1. **Default theme** loads first, populating the token map with baseline `[controls]` values.
2. **User theme** (e.g., `~/.config/omarchy/themes/custom/colors.toml`) loads second, shallow-merging its `[controls]` section into the default map.
3. **Runtime resolution** occurs when QML widgets request `Theme.controls.hover-bg` or similar properties.

As documented in [`docs/omarchy-shell.md`](https://github.com/basecamp/omarchy/blob/main/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:

```toml

# ~/.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:

```qml
// 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:

```bash

# Switch to the tokyo-night theme which includes its own [controls] definition

omarchy theme set tokyo-night

```

The shell references [`config/omarchy/shell.json`](https://github.com/basecamp/omarchy/blob/main/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 in [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) files 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.controls` accessors, enabling QML widgets to bind directly to configuration values.
- Source documentation in [`docs/theming.md`](https://github.com/basecamp/omarchy/blob/main/docs/theming.md) (line 275) and [`docs/omarchy-shell.md`](https://github.com/basecamp/omarchy/blob/main/docs/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`](https://github.com/basecamp/omarchy/blob/main/colors.toml) located within individual theme directories (e.g., [`themes/tokyo-night/colors.toml`](https://github.com/basecamp/omarchy/blob/main/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.