Guide · By Danylo Pravda · Updated
Theme a React app from one brand colour
Theming usually means a long list of variables: a primary colour, its hover, its pressed state, a focus ring, a text colour that stays readable on it, chart colours that match. Miss one and a button turns unreadable in light mode. Beamline derives all of them from one value, and keeps the rest of the look (type, corners, surfaces, motion) in a separate choice. This guide shows the three choices and what each one changes.
Choice one: the brand colour
import { UIRoot } from "@beamline/runtime";
import { prism } from "@beamline/look-prism";
<UIRoot preset={prism} theme="dark" brand="oklch(0.7 0.15 150)">
{children}
</UIRoot>
From that one colour come the accent, accent text, hover and pressed states, focus rings, selection tints, glows and
the first chart series. Text on a brand fill (a main button, a selected day, a checked box) picks its own ink from the
brand's lightness, so any brand keeps at least 4.5:1 contrast without a second colour. In plain CSS it is one
custom property, --pui-brand.
Write it in OKLCH and keep the lightness between 0.55 and 0.75: then the brand also reads as text on both themes.
Six ready accents swap only the brand (data-accent="neutral|violet|green|amber|orange|rose").
Choice two: light or dark
Dark is the default and the primary design target; theme="light" switches. Both themes define every token, so no
component ever branches on the theme, and a region can switch on its own with a UIRoot inside another.
Theme switch is a ready control for it.
Choice three: the look
Every part has a core (size, layout, states, keyboard, motion) and a look on top: the fonts, icon weight, corner radii, the page behind everything and the paint of every surface. Changing the look on the root restyles the whole app. There are nine:
| look | what it is |
|---|---|
| Prism (default) | cut crystal in a dark room: parts drawn by their cut edges, the main action white light, colour only where attention is |
| Soft | clean surfaces with a trace of your brand's hue, hairline rims, short shadows |
| Blueprint | the drafting table for dense tools: cyan wireframes, square corners, mono labels |
| Glass | a liquid lens: clear glass with bright rims over a faint grid |
| Metal | black anodised metal with diamond-cut edges, wide headings, monospaced figures |
| Glow | a calm night with light in one place: spectral light under the main buttons |
| Pop | a sticker sheet: a warm page, ink outlines, a hard lip under every control |
| Mono | monochrome: your brand colour appears only in the data it leads |
| Ink | a pen-and-ink drawing in two inks |
A look never changes the size scale (control heights, spacing), so switching it never reflows a layout beyond text following its fonts. You can set one for the app, one region, or a single part:
import { glass } from "@beamline/look-glass";
<UIRoot preset={glass} theme="light">…</UIRoot> // a region, its menus and dialogs included
<Button variant="accent" look="glow">Upgrade</Button> // one button
Every look is live in the component library: switch it there and every part on the page follows.
Smaller changes
For the rest, change a token or a default instead of a component:
<UIRoot
tokens={{ "--pui-radius-control": "12px" }}
defaults={{ button: { size: "sm" }, table: { density: "compact" } }}
>
{children}
</UIRoot>
- Tokens cover corner radii, surfaces, the three ink levels, chart series, motion timing and type faces; the
customise docs list them. Trading direction colours (
--pui-up,--pui-down) are separate from success and danger, so a market where red means up can swap them. - Defaults set a component's design props for a whole region (a smaller button, a compact table); a prop on one part still wins.
- Your own parts can wear the same paint with the look's role classes (
m-control,m-surface,m-fieldand the rest), so a custom widget matches whichever look is on.
What stays out of the theme
Nothing in a theme changes behaviour: keyboard models, focus order, data handling and motion rules belong to the core, and reduced motion is honoured in every look. Changing the brand or the look is safe to do late, even the day before a launch.
Ask your agent for it
With Beamline connected (setup for your agent): "use our brand colour #2F66D6 and the Soft look, light theme". The agent sets the brand and look on the root once and leaves every component alone. The full set of options is in Customise and the design language.