refract v0.1 · beta
Cookbook / Migrating CSS variables

Migrating CSS variables

Already have a hand-written :root of custom properties and a few utility classes? Moving to a RawTheme is mostly re-homing: variables become properties (grouped by subsystem), and your styled classes become recipes. In return you get tonal synthesis, composition, override(), and multi-format emit.

Before — hand-written CSS

styles.css
:root {
  --color-brand: #4c6ef5;
  --color-ink: #0e1117;
  --radius: 8px;
}
.btn {
  background: var(--color-brand); color: #fff;
  padding: 8px 14px; border: none; border-radius: var(--radius); cursor: pointer;
}

After — a RawTheme

Map each variable to a property under its subsystem; turn .btn into a colours recipe plus a component recipe that composes it. Raw values move into the css delta as bare literals; token references there use ref("…").

theme.ts
const raw = {
  colors: {
    brand: { base: "#4c6ef5", text: "#ffffff" },   // text = the on-colour
    ink:   { base: "#0e1117" },
    recipes: { solid: { brand: { background: "brand", color: "brand.text" } } },
  },
  borders: { radius: { base: 8 }, recipes: { edge: { button: { radius: "base" } } } },
  components: { recipes: { buttons: { primary: {
    colors: "solid.brand", borders: "edge.button",
    css: { padding: "8px 14px", border: "none", cursor: "pointer" },
  } } } },
};
// theme.getClass("components","buttons","primary")
// → "dt-colors-solid-brand dt-borders-edge-button dt-components-buttons-primary"
What you gain: brand now synthesizes light/dark steps you can reference; the button is composition (swap colors: for a whole reskin); and the same theme emits SCSS / JSON / styled-components. Migrate incrementally — a bare colors slice already produces useful :root vars. See RawTheme anatomy.
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.