Navigation

Theming and color scheme

Every visual value in Oblyx (color, spacing, radius, shadow, typography, motion) is a CSS custom property, prefixed --ox-. Components read these tokens; they never hardcode a color or a size. Change a token on :root and every component that reads it changes with it, with no component-level configuration.

Two attributes, two independent axes

Oblyx puts two attributes on the document root, and they control different things. Neither is required, both have a working default with zero attributes present.

<html data-color-scheme="dark" data-oblyx-theme="default"></html>

How light and dark are selected

data-color-scheme is resolved in three tiers, each one able to override the last:

  1. Default. With no attribute set and no OS preference detected, every color and shadow token resolves to its light value. This is the plain :root baseline in tokens.css.
  2. OS preference. A prefers-color-scheme: dark media query redefines the same tokens for dark, but only while the page hasn't explicitly opted into light. The media query is guarded with :root:not([data-color-scheme="light"]) so it can never win over an explicit choice.
  3. Explicit attribute. :root[data-color-scheme="dark"] always wins, over both the default and the OS preference, because it's the most specific selector and the last one in the cascade.

Net effect: explicit attribute beats OS preference beats light default. A page needs no JavaScript beyond setting or clearing data-color-scheme to move between all three states. This docs site's own light/dark switch, in the header, does exactly that: it toggles data-color-scheme on <html> and remembers the choice in localStorage. This page has no live components on it, but every one on the component pages reads the same token layer described below, so try the toggle there to see it in effect.

One theme today

Astryx, the design system Oblyx ports, ships seven named themes. Oblyx ships one,default, in the current release. The token layer and the data-oblyx-theme mechanism are built for more: a second theme is a new CSS file scoped to [data-oblyx-theme="name"] with @scope, redefining only the tokens that theme changes. It requires no change to any component, to tokens.css, or to the light/dark tiers above; a page that never loads a second theme's CSS is unaffected by its existence. There's no committed date for when a second theme ships. The point of documenting the mechanism now is that adding one later is a CSS-only addition, not a rework.

Overriding a token

Because every value is a plain custom property, overriding one is plain CSS: redeclare it at a scope that beats Oblyx's own declaration. The whole token catalog is visible in node_modules/oblyx/dist/oblyx.css (or packages/oblyx/src/styles/tokens.css in this repo), there's no separate reference document to look up a name from.

:root {
  --ox-color-accent: #7952ff;
}

Loaded after oblyx.css, this repaints every accent-colored surface across the whole page: button primaries, focus rings, checked states, the works, because they all read --ox-color-accent rather than a hardcoded blue. No build step, no component prop, no theme file required for a one-token tweak.