refract v0.1 · beta
Reference / FAQ

FAQ

Common questions about how — and why — refract works the way it does.

Why does core require an adapter — why no default?

Because the moment core has a default output, the Model isn't format-neutral any more — it quietly assumes CSS. Requiring an adapter keeps core holding zero output syntax: the same Model lowers to CSS, SCSS, JSON or styled-components with nothing baked in. It's one extra argument in exchange for the whole multi-format thesis. See createTheme.

Which colour inputs does refract accept, and why is var(--…) rejected?

A colour value has to be tonally derivable — refract synthesizes light/dark/numeric steps from it. Anything it can parse to concrete channels works: a hex string, an [r, g, b] tuple, oklch(), hsl()/hsla(), rgb()/rgba(), or a named keyword like "rebeccapurple" — all normalized to a canonical rgb() at build. The only inputs refused are var(--…), currentColor and transparent: a var() isn't known at build time, and the other two have no fixed channels to derive a ramp from. (Recipe declarations like color: "white" are unaffected — those are plain CSS.) See Colors.

Why OKLCH colour math?

Lightness derivations (lighten / darken / the numeric ladder) run in OKLCH, a perceptual space: equal lightness moves look even to the eye, and one lightness reads the same across hues — so blue.500 and red.500 land at the same lightness for free, and ramps don't muddy or blow out the way fixed-percentage RGB steps do. The maths is self-contained (Björn Ottosson's public-domain matrices, no dependency) and round-trips through rgb only at the boundary, so the Model still stores each colour as a canonical rgb() / rgba() string and the runtime graph carries no colour-space library. (DTCG export converts to hex, the DTCG convention.) Colours out of the sRGB gamut are handled by holding lightness and hue and easing chroma down — never by clipping channels, which would shift both.

Can I use refract alongside Tailwind (or any other CSS)?

Yes. refract emits its own namespaced surface — --<prefix>-… variables and .<prefix>-… classes (default dt, configurable) — so nothing collides with utilities or hand-written CSS. It contributes a stylesheet and class names; it doesn't take over the page. See Token paths & naming.

Is the run-time compile safe for user-supplied themes?

createTheme runs no eval — it consumes a plain object (the Playground uses JSON.parse, not code execution), so parsing an untrusted theme doesn't run untrusted code. The one thing to remember: injecting theme.css puts the theme author's values into a stylesheet, so treat an untrusted theme the way you'd treat untrusted CSS (it can style, not script). For fully-untrusted input, validate the shape and inject via a trusted <style>, not <link> to arbitrary URLs.

The trust boundary is your input. refract validates structure (colour parseability, token refs, units), not the content of literal declarations: a recipe or component css value (cursor: "pointer", content: "…") passes through to the output verbatim. So compiled output is only as trusted as the theme it came from — if you compile agent- or user-authored themes and serve the result, sanitize the literal css values first (reject stray }, </style>, or url()) exactly as you would any untrusted CSS. Token values (colours, lengths) are always re-serialized to a canonical form, so the passthrough surface is the literal css block only.

Why is DTCG an interop boundary and not an adapter?

An adapter is a rendering of the Model into an output format, and they're plural and swappable. DTCG is data interchange — a single, universal, property-token-only bridge to the design-token ecosystem, tightly coupled to the raw shape and token map. It doesn't render the Model; it moves tokens in and out. So it lives as fromDTCG / toDTCG at the ./dtcg subpath, not as a ThemeAdapter. See DTCG interop.

Missing a question? The Errors reference covers what the library throws and why, and every subsystem page documents its own authoring rules.
Technical documentation for @theme-registry/refract · all output is compiled client-side by the real library (CSS adapter). The chrome is theme-aware; the render panes carry each preset's own world. · MIT licensed.