# What Are the Standardized Interactive States for Controls in Omarchy Themes?

> Discover the four standardized interactive states in Omarchy themes Normal Hover Focus and Selected for consistent UI feedback using reusable tokens in shell themes

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: deep-dive
- Published: 2026-08-30

---

**Omarchy themes define four standardized interactive states—Normal, Hover/Cursor, Focus, and Selected—that provide consistent visual feedback across all UI controls through reusable tokens in the `[controls]` section of shell themes.**

Omarchy implements a unified theming system that standardizes how buttons, dropdowns, and tab strips respond to user interaction. The standardized interactive states for controls in Omarchy themes are defined in the `[controls]` section of shell theme configuration files, allowing theme authors to manage appearance globally while ensuring consistent feedback throughout the Qt-based desktop environment.

## The Four Standardized Interactive States

According to [`docs/omarchy-shell.md`](https://github.com/omacom/omarchy/blob/main/docs/omarchy-shell.md), the `[controls]` section specifies four distinct states that every interactive element can reference. Each state exposes five token types: color, fill alpha, border, border width, and border alpha.

### Normal (Idle State)

The default appearance when no interaction occurs. This state uses `normal-color`, `normal-fill-alpha`, `normal-border`, `normal-border-width`, and `normal-border-alpha` tokens to define the control's resting visual state.

### Hover / Cursor State

Triggered when the cursor enters the control area. This state employs `hover-cursor-color`, `hover-cursor-fill-alpha`, `hover-cursor-border`, `hover-cursor-border-width`, and `hover-cursor-border-alpha` tokens to provide immediate visual feedback during mouse navigation.

### Focus State

Indicates Qt `activeFocus` when a control has keyboard focus. Governed by `focus-color`, `focus-fill-alpha`, `focus-border`, `focus-border-width`, and `focus-border-alpha` tokens, this state ensures accessibility by clearly identifying which element receives keyboard input.

### Selected State

A persistent selection state for toggled or active items. Managed through `selected-color`, `selected-fill-alpha`, `selected-border`, `selected-border-width`, and `selected-border-alpha` tokens, this state maintains visual indication of ongoing selection.

## Token Architecture and Value Types

Each state token supports specific value types that determine rendering behavior:

- **Color tokens**: Reference palette roles (`foreground`, `accent`, `urgent`, `background`) or raw hex strings
- **Fill alpha**: Controls background opacity independently of the color value
- **Border tokens**: Accept solid colors or gradient definitions using the syntax `rgba() rgba() angle`
- **Border width**: Integer values where `0` disables the border while preserving fill colors
- **Border alpha**: Controls border opacity separately from fill alpha

## Configuring States in Theme Files

Themes implement these states in [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml) or [`theme.toml`](https://github.com/omacom/omarchy/blob/main/theme.toml) files located in paths such as [`default/themes/gravitas/shell.toml`](https://github.com/omacom/omarchy/blob/main/default/themes/gravitas/shell.toml). The configuration maps state tokens to palette roles or specific color values:

```toml
[controls]

# Map states to palette roles

hover-cursor-color = "accent"
focus-color        = "accent"
selected-color     = "foreground"

# Gradient borders for interactive states

hover-cursor-border = "rgba(33ccffee) rgba(00ff99ee) 45deg"
focus-border        = "rgba(33ccffee) rgba(00ff99ee) 45deg"

# Solid border with disabled state example

selected-border        = "rgba(00ff99ff) 1px solid"
selected-border-width  = 0

```

## QML Integration via Style Helpers

The `shell/Ui/Style.qml` file provides runtime resolution through helper functions that map token names to actual colors. QML components consume these tokens via `qs.Style` and `qs.Border` helpers:

```qml
import QtQuick 2.15
import qs 1.0

Rectangle {
    id: control
    color: Style.controlColor("normal")
    border.color: Style.controlBorder("normal")
    border.width: Style.controlBorderWidth("normal")

    MouseArea {
        anchors.fill: parent
        hoverEnabled: true
        onEntered: control.color = Style.controlColor("hover-cursor")
        onExited:  control.color = Style.controlColor("normal")
        onPressed: control.color = Style.controlColor("selected")
    }
}

```

The `shell/Ui/Border.qml` component handles border-specific rendering, supporting both solid colors and gradient definitions specified in the theme tokens.

## Scope Limitations for Specialized Surfaces

While `[controls]` governs shared button and dropdown chrome, specific surfaces maintain independent token sets. The `[menu]`, `[launcher]`, and `[image-picker]` sections define their own `selected-*` tokens and do not inherit from `[controls]`. This architectural decision allows specialized styling for distinct UI contexts while keeping the shared control chrome consistent.

## Summary

- Omarchy themes standardize **four interactive states**—Normal, Hover/Cursor, Focus, and Selected—through the `[controls]` section in shell themes as documented in [`docs/omarchy-shell.md`](https://github.com/omacom/omarchy/blob/main/docs/omarchy-shell.md).
- Each state exposes **color**, **fill alpha**, **border**, **border width**, and **border alpha** tokens for granular visual control.
- Theme authors configure these in [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml) files, referencing palette roles or raw values, with full support for gradient borders.
- QML components consume tokens via `Style.controlColor()` and `Style.controlBorder()` helpers implemented in `shell/Ui/Style.qml`.
- **Specialized surfaces** like menus and launchers maintain separate token sets and do not inherit `[controls]` definitions, allowing context-specific styling.

## Frequently Asked Questions

### How do I disable borders while keeping fill colors in Omarchy themes?

Set the specific state's border width token to `0`. For example, `selected-border-width = 0` removes the selected state's border while preserving the `selected-color` fill and its alpha value defined in your [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml).

### Can Omarchy theme borders use gradients instead of solid colors?

Yes. Border tokens accept gradient definitions using the syntax `rgba() rgba() angle`. For instance, `hover-cursor-border = "rgba(33ccffee) rgba(00ff99ee) 45deg"` creates a 45-degree gradient between two semi-transparent colors, processed by the `shell/Ui/Border.qml` helper.

### Why don't menu selections use the [controls] selected state?

Surfaces like `[menu]`, `[launcher]`, and `[image-picker]` define their own `selected-*` tokens independent of `[controls]`. According to the Omarchy shell documentation, these specialized UI contexts require distinct visual treatment and therefore do not inherit the shared control chrome tokens, allowing separate customization for menus versus buttons.

### What is the difference between fill alpha and border alpha tokens?

**Fill alpha** controls the opacity of the state's background color (resolved by `Style.controlColor()`), while **border alpha** controls the opacity of the border stroke specifically (resolved by `Style.controlBorder()`). This separation allows themes to create controls with opaque borders but semi-transparent backgrounds, or vice versa, without modifying the underlying color values.