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​