# How Omarchy Integrates Color and Style Singletons for Theme-Consistent UI

> Discover how Omarchy integrates Color and Style singletons to ensure theme consistency across your UI. Learn about their single source of truth for design tokens.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: internals
- Published: 2026-09-03

---

**Omarchy uses Quickshell QML singletons—`Color` and `Style` declared in `shell/Commons/qmldir`—to provide a single source of truth for theme colors and design tokens across the entire desktop environment.**

Omarchy's visual architecture centers on two critical singletons that eliminate state duplication and enable instant theme switching. This article explains how the **Color** and **Style** singletons are registered, loaded, and consumed throughout the shell, with specific reference to the `omacom/omarchy` source code.

## What Are the Color and Style Singletons?

Omarchy defines three core QML singletons in `shell/Commons/qmldir`:

```qml
singleton Border 1.0 Border.qml
singleton Color  1.0 Color.qml
singleton Style  1.0 Style.qml
singleton Util   1.0 Util.qml

```

- **Color** (`shell/Commons/Color.qml`): Exports theme-derived color palettes and surface-specific color roles
- **Style** (`shell/Commons/Style.qml`): Provides typographic, spacing, and widget-level design tokens

Both use `pragma Singleton` to guarantee exactly one instance per session. This design pattern ensures that when a theme changes, every UI element updates simultaneously without re-instantiating components.

## How the Color Singleton Works

The **Color** singleton parses theme configuration and exposes reactive color properties. Located at `shell/Commons/Color.qml`, it begins with:

```qml
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
import "BorderGeometry.js" as Geometry

```

### Theme Parsing and Color Resolution

Color reads [`colors.toml`](https://github.com/omacom/omarchy/blob/main/colors.toml) from the active theme directory and [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml) from generated configuration. It exposes:

- `shellValues`: Flat dictionary mapping `"section.key"` strings to raw TOML values
- Helper functions: `pick()`, `pickAlpha()`, `flatColor()`, `composed()`

Surface-specific color objects use nested `QtObject` declarations:

```qml
readonly property QtObject bar: QtObject {
    property color background: root.composed("bar.background",
                                            "bar.background-alpha",
                                            root.background, 1.0)
    property color text:       root.pick("bar.text", root.foreground)
    property color active:     root.pick("bar.active", root.urgent)
}

```

This creates type-safe, theme-aware color roles that components import:

```qml
import "Color.qml" as Color

Rectangle {
    color: Color.bar.background
    Text {
        color: Color.bar.text
    }
}

```

Theme switching updates `shellValues`, triggering QML's reactive binding system to re-evaluate every color reference automatically.

## How the Style Singleton Works

The **Style** singleton (`shell/Commons/Style.qml`) follows identical singleton semantics:

```qml
pragma Singleton
import QtQuick

QtObject {
    readonly property int borderRadius: 6
    readonly property int padding: 8
    readonly property string fontFamily: "Ubuntu"
    readonly property int   fontSize: 12
    readonly property real  animationDuration: 0.15
}

```

### Design Token Consumption

Components reference Style properties directly for layout consistency:

```qml
import "Style.qml" as Style

Text {
    font.family: Style.fontFamily
    font.pixelSize: Style.fontSize
    leftPadding: Style.padding
}

```

Because Style is a singleton, typography and spacing changes propagate instantly without component recompilation or manual refresh calls.

## Integration Architecture

Omarchy's singleton integration follows three phases:

1. **Registration** – `shell/Commons/qmldir` declares singletons; Quickshell loads them into the QML engine's import path during `shell/shell.qml` initialization
2. **Binding** – UI components bind to `Color.*` and `Style.*` properties; QML's property system maintains reactive dependencies
3. **Mutation** – Theme changes update singleton internal state; all bound properties re-evaluate simultaneously

### Why Singletons Instead of Regular Imports?

Regular QML imports create new instances per import site. True **singletons** (via `pragma Singleton` + `qmldir` registration) share identical object identity across all importers. This eliminates:

- Per-component state duplication
- Synchronization bugs between panels
- Race conditions during theme transitions

## Practical Code Examples

### Complete Plugin Using Both Singletons

```qml
import QtQuick
import "Color.qml" as Color
import "Style.qml" as Style

Rectangle {
    width: 200
    height: 40
    color: Color.bar.background
    radius: Style.borderRadius
    
    Text {
        anchors.centerIn: parent
        text: "Omarchy"
        color: Color.bar.text
        font.family: Style.fontFamily
        font.pixelSize: Style.fontSize
    }
}

```

### Layout with Style Tokens

```qml
import "Style.qml" as Style

Row {
    spacing: Style.padding
    Rectangle { 
        width: 30; height: 30; 
        color: "red" 
        radius: Style.borderRadius 
    }
    Rectangle { 
        width: 30; height: 30; 
        color: "green" 
        radius: Style.borderRadius 
    }
}

```

### Theme Switching Implementation

In `shell/shell.qml`, theme changes propagate through the Color singleton:

```qml
Connections {
    target: OmarchyTheme
    onThemeChanged: {
        Color.shellValues = OmarchyTheme.loadShellToml()
        // All Color.* bindings refresh automatically
    }
}

```

## Key Implementation Files

| File | Purpose | Location |
|------|---------|----------|
| `shell/Commons/qmldir` | Singleton registration | `shell/Commons/qmldir` |
| `shell/Commons/Color.qml` | Theme color parsing and surface roles | `shell/Commons/Color.qml` |
| `shell/Commons/Style.qml` | Typography and spacing tokens | `shell/Commons/Style.qml` |
| `shell/shell.qml` | Entry point, theme loading | `shell/shell.qml` |
| [`docs/theming.md`](https://github.com/omacom/omarchy/blob/main/docs/theming.md) | Theme configuration format | [`docs/theming.md`](https://github.com/omacom/omarchy/blob/main/docs/theming.md) |

## Summary

- **Color and Style singletons** in Omarchy provide centralized, reactive theme properties via `pragma Singleton` and `shell/Commons/qmldir` registration
- **Color** parses [`colors.toml`](https://github.com/omacom/omarchy/blob/main/colors.toml) and [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml), exposing surface-specific color objects with helper functions for gradient, alpha, and fallback handling
- **Style** exports immutable design tokens for typography, spacing, radius, and animation timing
- **QML's reactive binding system** ensures instant UI updates when singleton state changes, eliminating manual refresh logic
- **True singleton semantics** prevent state duplication and race conditions across multiple panels and plugins

## Frequently Asked Questions

### What makes Omarchy's Color and Style singletons different from regular QML modules?

Regular QML imports create distinct instances per import location. Omarchy's use of `pragma Singleton` combined with `qmldir` registration ensures exactly one object identity shared across all importers. This guarantees that updating `Color.shellValues` immediately affects every component binding to `Color.*` properties.

### How does Omarchy handle theme switching without restarting the shell?

The Color singleton's `shellValues` property is replaced when `OmarchyTheme.loadShellToml()` returns new configuration. Because all color properties are computed from `shellValues` through QML bindings, the reactive system re-evaluates every dependent property automatically. No manual component refresh or shell restart is required.

### Can I extend the Style singleton with custom design tokens?

Yes. Since `Style.qml` is a standard QML singleton, you can add readonly properties following the existing pattern. Changes to `shell/Commons/Style.qml` propagate to all importers immediately. For theme-specific style overrides, consider adding computed properties that read from `Color.shellValues` similar to how `Color` handles theme-dependent values.

### Where does Omarchy load theme data from?

The Color singleton reads `themes/*/colors.toml` for color definitions and generated [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml) for shell-specific overrides. These paths are resolved relative to the active theme directory, which `shell/shell.qml` configures during startup. The [`docs/theming.md`](https://github.com/omacom/omarchy/blob/main/docs/theming.md) file documents the complete TOML schema for theme authors.