Back to Aionui

Custom Themes - Authoring Guide

docs/guides/custom-theme.md

2.1.587.9 KB
Original Source

Custom Themes - Authoring Guide

AionUi ships with Light and Dark themes, but you can create your own color themes without touching any code. A custom theme is just a small block of CSS that overrides a set of documented theme variables (CSS custom properties). This guide shows you exactly what to write and how to apply it.


How theming works

Every surface in AionUi reads its colors from a fixed set of semantic variables rather than hardcoded values. For example, the accent color is always var(--primary), the main background is always var(--bg-base), and so on. A theme simply supplies new values for those variables.

Your custom theme layers on top of the built-in Light or Dark baseline:

  • You pick a base appearance (light or dark) when you create the theme. That decides the starting point (default neutrals, Arco Design widget styling, scrollbars, etc.).
  • Your CSS then overrides only the variables you care about. Anything you don't override keeps its baseline value, so you never have to redefine the whole palette.

Two selectors are recognized:

SelectorApplies toUse it for
:root { … }AlwaysYour main palette (matches the base appearance you chose).
[data-theme='dark'] { … }Only in dark modeOptional dark-mode-specific overrides.

If you only target one appearance, a single :root { … } block is enough.


Add a custom theme (step by step)

  1. Open Settings → Appearance.
  2. Under the theme gallery, choose Add a custom theme.
  3. Fill in the form:
    • Name — anything, e.g. Neo-Brutalism.
    • Base appearanceLight or Dark. Pick the one closest to your target so you override fewer variables.
    • CSS — paste your theme CSS (see below).
  4. Watch the live preview update as you type.
  5. Save. Your theme now appears in the gallery; click it to activate.

Custom themes are stored in your local config and are applied across all app windows. You can edit or delete them any time from the same screen.


Writing the CSS

Rules of the road:

  • Only override the documented variables in the Available variables table. Unknown / misspelled variables are ignored.
  • Always include the -- prefix, e.g. --primary: #ff5c00;.
  • Keep enough contrast. Text variables must stay readable on their matching backgrounds. Aim for a WCAG AA contrast ratio (≥ 4.5:1 for body text).
  • !important is handled for you. The app sandboxes your CSS and raises its specificity automatically, so you don't need to add !important yourself.

A minimal theme looks like this:

css
:root {
  --primary: #ff5c00;
  --bg-base: #fffdf5;
  --text-primary: #111111;
}

To also tweak dark mode, add a second block:

css
:root {
  --primary: #ff5c00;
}
[data-theme='dark'] {
  --primary: #ffa562;
}

Available variables

These are the variables a theme may override, grouped by purpose. Values shown are the Light baseline, for reference.

Backgrounds

VariableBaseline (Light)Meaning
--bg-base#ffffffPrimary app background
--bg-1#f9fafbSecondary background
--bg-2#f2f3f5Tertiary background
--bg-3#e5e6ebBorder / divider background
--bg-6#86909cDisabled / secondary icon fill
--bg-hover#f3f4f6Hover background
--bg-activeActive / pressed background

Text

VariableMeaning
--text-primaryPrimary text
--text-secondarySecondary text
--text-disabledDisabled text
--text-whiteAlways-white text (same in light & dark)

Borders

VariableMeaning
--border-baseBase border
--border-lightLight border
--border-specialSpecial-case border

Semantic colors

VariableMeaning
--primaryPrimary / accent color
--successSuccess color
--warningWarning color
--dangerDanger / error color
--infoInfo color

Brand

VariableMeaning
--brandBrand color
--brand-lightBrand light background
--brand-hoverBrand hover color

Components

VariableMeaning
--message-user-bgUser message bubble background
--message-tips-bgTips message background
--workspace-btn-bgWorkspace button background
--thought-gradientThinking panel background (accepts a linear-gradient(...))

Special

VariableMeaning
--fillGeneric fill
--fill-0Fill 0
--dialog-fill-0Dialog fill
--inverseInverse (always white)

The authoritative list lives in packages/desktop/src/common/theme/tokenContract.ts. Arco Design's internal scales (--color-*, --primary-6, …) are not part of this contract and are driven by the base appearance instead.


Full example

A complete, readable starter theme. Copy it into the CSS field, choose Light as the base appearance, and save.

css
:root {
  --primary: #4f46e5;
  --info: #4f46e5;
  --brand: #4f46e5;
  --brand-hover: #6366f1;
  --brand-light: #eef2ff;

  --bg-base: #fbfbfe;
  --bg-1: #f4f4fb;
  --bg-2: #ececf7;

  --text-primary: #1a1a2e;
  --text-secondary: #4b4b63;

  --message-user-bg: #eef2ff;
  --message-tips-bg: #f5f3ff;
}

For a ready-made, high-contrast theme, see the Neo-Brutalism theme in docs/theming/examples/neo-brutalism.css.


Tips & troubleshooting

  • Nothing changed after saving. Make sure you activated the theme (click its card in the gallery), and that you overrode a variable that's actually visible on screen — e.g. --primary shows on buttons/links, --bg-base is the whole background.
  • My variable is ignored. Check the exact name against the Available variables table (including the -- prefix). Unknown variables are silently dropped.
  • Text is hard to read. You probably changed a background without updating the matching text color. Adjust --text-primary / --text-secondary to keep contrast.
  • Dark mode looks off. Add a [data-theme='dark'] { … } block with dark-appropriate values; light values rarely translate directly to dark.
  • I want to share my theme. Just share the CSS block — anyone can paste it into their own Add a custom theme form.