# How to Use the BorderSurface QML API in Omarchy

> Learn to use the BorderSurface QML API in Omarchy. Render native borders or complex gradients with the borderSpec property for optimized visuals.

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

---

**The `BorderSurface` component in Omarchy accepts a `borderSpec` property—created via the `Border` singleton—to render optimized native borders or complex gradient/per-side borders through an automatic overlay fallback.**

Omarchy's UI toolkit provides a standardized way to add borders to any rectangular element through the `BorderSurface` QML API. This component lives in `shell/Ui/BorderSurface.qml` and integrates with the `Border` singleton (`shell/Commons/Border.qml`) to deliver theme-aware, performant borders across the desktop environment. This guide shows you how to use the BorderSurface API with practical, runnable examples.

## Core Architecture of the BorderSurface API

Understanding the three key components helps you use the API effectively.

| Component | Location | Purpose |
|-----------|----------|---------|
| **`BorderSurface`** | `shell/Ui/BorderSurface.qml` | Rectangle-derived wrapper that exposes `borderSpec`, padding properties, and automatic `BorderOverlay` loading |
| **`Border`** | `shell/Commons/Border.qml` | Singleton factory for creating border specifications with helpers like `canUseNative()`, `needsOverlay()`, and per-side width accessors |
| **`BorderOverlay`** | `shell/Ui/BorderOverlay.qml` | Shape-based renderer for non-uniform borders or gradients when native `Rectangle.border` is insufficient |

### How BorderSurface Renders Borders

When you assign a `borderSpec` to `BorderSurface`, the component follows this decision path:

1. **Evaluate the specification** — `Border.canUseNative(borderSpec)` checks if the border can use the cheap native `Rectangle.border` property (uniform width, solid color, no gradient).

2. **Choose rendering path** — 
   - **Native path**: Direct assignment to `Rectangle.border` for maximum performance
   - **Overlay path**: Sets `usesOverlayBorder` to true and loads `BorderOverlay` via a `Loader` to draw complex borders

3. **Compute content insets** — Read-only properties `contentTopInset`, `contentRightInset`, `contentBottomInset`, and `contentLeftInset` combine resolved border widths with padding values so child items position correctly.

## Creating Border Specifications with the Border Singleton

The `Border` singleton provides factory methods for common specification patterns.

### Border.flat() — Simple Static Borders

Use `Border.flat(color, width)` for uniform, solid-color borders.

```qml
import QtQuick 2.15
import qs.Commons  // Brings in Border singleton

BorderSurface {
    width: 200
    height: 100
    borderSpec: Border.flat("#4a90e2", 3)   // 3 px solid blue border
    padding: 8

    Text {
        anchors.centerIn: parent
        text: "Hello Omarchy"
        color: "#fff"
    }
}

```

### Border.surfaceSpec() — Theme-Driven Borders

Use `Border.surfaceSpec(section, token, fallbackColor, fallbackWidth, alphaKey)` to resolve values from Omarchy's theme configuration.

```qml
import QtQuick 2.15
import qs.Commons

BorderSurface {
    width: 300
    height: 150
    borderSpec: Border.surfaceSpec("panel", "border", "#222", 1, "border-alpha")
    padding: 12

    Image {
        anchors.fill: parent
        source: "qrc:/icons/logo.svg"
        fillMode: Image.PreserveAspectFit
    }
}

```

This example pulls the border definition from the `[panel]` section of the theme, using the `border` token with fallback values and alpha channel lookup.

## Advanced Gradient and Per-Side Borders

When you need gradients or non-uniform widths, `BorderSurface` automatically falls back to `BorderOverlay`.

### Gradient Border with Manual Specification

```qml
import QtQuick 2.15
import qs.Commons

BorderSurface {
    width: 250
    height: 120

    borderSpec: {
        let spec = Border.flat("transparent", 0);
        spec.gradient = { 
            colors: ["#ff7e5f", "#feb47b"], 
            angle: 45, 
            enabled: true 
        };
        spec.widths = { top: 4, right: 4, bottom: 4, left: 4 };
        return spec;
    }

    padding: 10

    Rectangle {
        anchors.fill: parent
        color: "#1e1e1e"
        radius: 8
    }
}

```

The presence of `gradient.enabled: true` triggers `Border.needsOverlay(spec)` to return true, causing `BorderSurface` to instantiate `BorderOverlay` internally.

## Controlling Padding and Content Insets

`BorderSurface` provides flexible padding control that combines with border widths to produce final content insets.

### Padding Properties

| Property | Default | Description |
|----------|---------|-------------|
| `padding` | `0` | Sets all sides to the same value |
| `topPadding` | `padding` | Overrides top inset |
| `rightPadding` | `padding` | Overrides right inset |
| `bottomPadding` | `padding` | Overrides bottom inset |
| `leftPadding` | `padding` | Overrides left inset |

### Content Inset Properties (Read-Only)

These computed properties tell child items how much space to leave for borders and padding:

- `contentTopInset` = `borderSpec.topWidth + topPadding`
- `contentRightInset` = `borderSpec.rightWidth + rightPadding`
- `contentBottomInset` = `borderSpec.bottomWidth + bottomPadding`
- `contentLeftInset` = `borderSpec.leftWidth + leftPadding`

Use these when positioning children that must not overlap the border area:

```qml
BorderSurface {
    id: surface
    borderSpec: Border.surfaceSpec("window", "border", "#333", 2)
    padding: 10

    Text {
        anchors {
            top: parent.top
            left: parent.left
            topMargin: surface.contentTopInset
            leftMargin: surface.contentLeftInset
        }
        text: "Positioned inside border"
    }
}

```

## Helper Utilities in BorderGeometry.js

The [`shell/Commons/BorderGeometry.js`](https://github.com/omacom/omarchy/blob/main/shell/Commons/BorderGeometry.js) module provides low-level utilities used by both `Border` and `BorderSurface`:

- Width string parsing (e.g., `"1 2 3 4"` → per-side values)
- Maximum width calculation for overlay bounds
- Overlay need detection based on specification complexity

You rarely interact with this directly, but it's available for custom border implementations.

## Summary

- **`BorderSurface`** (`shell/Ui/BorderSurface.qml`) is the primary component for bordered rectangles in Omarchy

- **`Border`** singleton (`shell/Commons/Border.qml`) creates specifications via `Border.flat()` and `Border.surfaceSpec()`

- **Automatic optimization** — Native `Rectangle.border` for simple borders, `BorderOverlay` for gradients and per-side widths

- **Computed insets** — `contentTopInset` and siblings combine border widths with padding for proper child positioning

- **Theme integration** — `Border.surfaceSpec()` resolves values from Omarchy's centralized theme configuration

## Frequently Asked Questions

### How do I know if my border will use the native or overlay renderer?

Call `Border.canUseNative(borderSpec)` or check `Border.needsOverlay(borderSpec)` before assignment. Native rendering requires uniform width, solid color, and no gradient. Any deviation triggers overlay fallback.

### Can I use BorderSurface without importing qs.Commons?

No. The `Border` singleton lives in `qs.Commons`, so you must import it to create valid `borderSpec` objects. The `BorderSurface` type itself comes from `qs.Ui` or your local `shell/Ui` import path.

### What happens if the theme token doesn't exist in surfaceSpec()?

`Border.surfaceSpec()` uses the `fallbackColor` and `fallbackWidth` parameters you provide. In the example `Border.surfaceSpec("panel", "border", "#222", 1, "border-alpha")`, a missing `panel.border` token results in a 1-pixel `#222` border.

### Is there a performance cost to gradient borders?

Yes. Gradient borders always use `BorderOverlay`, which creates a `Shape` item with `ShapePath` elements. This is more expensive than native `Rectangle.border` but necessary for visual effects that Qt Quick's native border cannot express.