Skip to main content
Version: 3.x

Admin theming — the --cb- token layer, light / dark / auto

Version
3.x
Updated
View markdown

Scope: how the CBX backend decides its colour scheme and where its colours come from — the data-bs-theme anchor, getAdminColorScheme() per platform, the --cb-* token set, the vendor overrides, and the rules custom admin CSS has to follow · Last reviewed: 2026-08-25

The CBX backend follows a light / dark / auto colour scheme, and every colour in it comes from one token layer: assets/css/admin-theme.css. This page is the reference for that layer. For the other admin stylesheet mechanism — the per-host anti-bleed files that adapt CBX to each host's chrome — see com_configbox_host_stylesheets.md; host stylesheets consume these tokens and do not define them.


1. The anchor: data-bs-theme

CBX's namespaced Bootstrap 5.3 uses the standard data-bs-theme="light|dark" colour-mode attribute and defines its --bs-* variables per scheme. The --cb-* tokens hang off the same attribute, so CBX's colours and Bootstrap's flip together rather than drifting apart.

There is no JavaScript in the decision. Three cases cover everything:

SituationWhat sets the scheme
An ancestor carries data-bs-theme="dark"The explicit-dark block applies
An ancestor carries data-bs-theme="light"Nothing overrides the light defaults — and the OS fallback is suppressed
No attribute at all (auto)@media (prefers-color-scheme: dark) applies the dark tokens

The auto block is guarded as :root:not([data-bs-theme="light"]) …:not([data-bs-theme="light"]), so an explicit light choice beats a dark OS. That mirrors Bootstrap's own media-query colour-mode strategy.

2. How each platform resolves it — getAdminColorScheme()

KenedoPlatform::getAdminColorScheme() is the platform contract, and the answers differ because the hosts differ:

HostReturnsWhy
Joomlathe resolved schemeThe Atum admin template already stamps data-bs-theme on <html> from its own light/dark/auto setting, and CBX renders inside it — so it inherits for free. The method still reports the resolved value (an explicit userColorScheme cookie first, then the user's colorScheme profile parameter) for callers that need it server-side.
WordPress'light'The WP backend is light-only and gives no light/dark signal. Its admin colour schemes only restyle the menu, toolbar and accents; the content area CBX renders into stays light in all of them.
Magento 2'light'The Magento backend theme is light-only and has no dark mode.
standalone'auto'No host chrome and no host signal, so CBX follows the OS.

Why the two light-only hosts pin rather than report auto: reporting auto would let prefers-color-scheme darken CBX alone, leaving a dark CBX panel sitting inside permanently light host chrome. Pinning light keeps the two in step. On those hosts KenedoView stamps data-bs-theme="light" on the admin view wrapper, which also suppresses the OS fallback in admin-theme.css.

If WordPress or Magento ever ships an admin dark mode, that platform's getAdminColorScheme() is the one place to read its signal.

3. The tokens

Tokens are defined on four roots, not one: .cb-content (every CBX view wrapper, and where the namespaced Bootstrap is scoped), body.admin.com_configbox and .configbox-admin-index (host page wrappers that admin.css paints with --cb-body-bg, and which sit above .cb-content), and .kenedo-popup.

.kenedo-popup is a token root of its own for a reason. KenedoPopup.open() clones the popup out of the view wrapper and appends it to <body>, so it cannot inherit tokens from .cb-content — and on a host where the body itself carries tokens, it would otherwise pick up the body's scheme instead of the one its origin resolved to. kenedo.js stamps the origin's effective data-bs-theme onto the clone; unstamped means auto, and the media block takes over.

The set, by group:

GroupTokens
Surfaces--cb-body-bg (tracks Joomla Atum's grey via --template-bg-light), --cb-surface, --cb-surface-2, --cb-surface-3, --cb-overlay
Text--cb-text, --cb-text-strong, --cb-text-muted, --cb-text-faint, --cb-text-inverse
Borders--cb-border, --cb-border-strong, --cb-border-subtle
Brand & links--cb-brand, --cb-brand-contrast, --cb-link, --cb-link-hover, --cb-accent
Semantic--cb-success, --cb-warning, --cb-danger, --cb-info, --cb-required, each with a -bg twin
Form fields--cb-input-bg, --cb-input-text, --cb-input-border, --cb-input-focus-border
Buttons--cb-primary (+ -border, -hover, -hover-border), --cb-btn-bg, --cb-btn-text, --cb-btn-border, --cb-btn-hover-bg, --cb-btn-hover-border
Elevation--cb-shadow-sm, --cb-shadow, --cb-inset-shadow
Editor palettenode/token fills for the calc, rule and matrix editors, tuned to stay legible on both schemes

One token is not a colour and catches people out: --cb-select-caret is Tom Select's single-select caret as a background-image SVG with the stroke colour baked into the data URI — it cannot reference a variable, so it is swapped wholesale per scheme. Its stroke mirrors --cb-text-muted; change one and change the other.

4. Vendor chrome

Two vendored widgets do not read CSS variables and need explicit per-scheme rules, which admin-theme.css carries for both the explicit-dark and the auto-dark cases: Tom Select (the enhanced dropdowns — control, dropdown, options, multi-select items, the remove button) and jQuery UI (the availability datepicker and any sortable/dialog chrome).

Also here: the CBX heading logo is dark artwork, so it gets a legibility treatment on dark surfaces.

5. Rules for custom admin CSS

  1. Reference the tokens, never hardcode. A hex value in custom admin CSS is a light-mode bug waiting for someone to switch to dark. Use --cb-* (and --bs-* where Bootstrap owns the component).
  2. Do not restyle in a [data-bs-theme] or media block. Define your component once against the tokens; the tokens already flip. A colour whose only definition sits inside a dark block will not apply in the unstamped auto state.
  3. Edit values here, not in the consuming file. admin-theme.css is the single source of colour; admin.css, general.css, the calc/rule/matrix editors and the per-property CSS all consume it.
  4. Check both schemes before calling it done. Everything in the admin can be viewed light and dark; an interactive state that was only ever seen in one is only half-checked.
  5. .min.css twins are build artifacts — regenerated by the packager, not edited.

6. See also