Theme generator.
Design your brand visually — tune colors,
corner radius, typography,
spacing, shadows and
gradients and watch a real Aktion UI update live.
When it looks right, copy the ready‑to‑paste
$theme({…}) statement and drop it into
any program.
$theme(…) output
$theme({})
How to use it
The generator starts from one of the six built‑in themes
(Start from). Every control you touch becomes an
override layered on top of that base — so the output stays
minimal and only contains what you actually changed. Pick a colour preset
for an instant palette, fine‑tune individual tokens, then copy the
generated $theme({…}).
- Choose a base. It seeds the surfaces, type, and defaults you build on top of.
- Tune tokens. Colours, roundness, density, typography, elevation and a brand gradient — the preview re‑skins instantly.
- Copy the statement. Hover the code block and hit
Copy, then paste the
$theme({…})at the top of any Aktion program.
Every value in the panel is read back from the runtime rather than hardcoded here, so the base defaults you see are the ones the library actually ships.
Using the generated theme
A bare $theme({…}) statement lives at the top level of a
program, alongside your $app(…) root. The runtime writes the
tokens to the host element as CSS variables and re‑skins every component
— no stylesheet, no rebuild:
$theme({
name: "light",
colors: { primary: "#7c3aed", primaryHover: "#6d28d9", accent: "#06b6d4" },
radius: { md: "14px", button: "999px" }
})
$app(Column([
Card([
CardHeader("Branded card"),
Row([
Button("Primary", { variant: "primary" }),
Button("Ghost", { variant: "ghost" })
], { gap: "sm" })
])
], { gap: "md" }))
Grouped tokens, not flat keys
Inside $theme({…}) tokens live in groups
(colors.primary, radius.md,
font.familyHeading) — that is exactly what this generator
emits. The optional name key selects a built‑in theme as the
base palette before your overrides layer on top. Flat keys like
colorPrimary are not accepted here — those belong on
the host theme attribute / setTheme().
Setting it on the host instead
The same palette can be applied imperatively on the
<aktion-app> element — handy for a user‑facing theme
switcher. The host path takes a built‑in name or a flat
token map:
const app = document.querySelector("aktion-app");
app.setTheme("dark"); // a built-in name
app.setTheme({ colorPrimary: "#7c3aed", // flat token overrides
radiusMd: "14px" });
Use $theme({…}) (grouped) inside a program for a
per‑response brand; use setTheme() (flat) on the host for an
app‑wide base. The flat shape is also the only one that reaches all 113
tokens. See Themes & customization for the full
token reference.
What the generator controls
Six of the ten token groups have controls here. They are the ones that change how a UI feels; the rest are better set by hand once, and are listed below.
| Group | Tokens |
|---|---|
colors | Brand (primary, accent, focusRing), surfaces (bg, surface, border, borderControl), text, status fills (success / warning / danger / info) and their text‑safe partners (successText, onSuccess, …). |
radius | One roundness slider drives xs…lg plus button/input; a pill toggle rounds buttons fully. |
spacing | A density control scales the xs…xl spacing ramp behind every gap/padding. |
font | Body & heading families (with on‑demand web‑font loading), base size, and heading weight. |
shadows | An elevation preset sets the sm/md/lg shadow ramp. |
gradients | A two‑stop brand gradient powering GradientText and sx.bg: "gradient.brand". |
The generator does not emit zIndex or motion, but both
are real $theme groups — add them to the copied
statement by hand:
$theme({
zIndex: { modal: 2000, toast: 2100 },
motion: { fast: "100ms", base: "160ms", ease: "cubic-bezier(.2,.8,.2,1)" }
})
What genuinely cannot be expressed in the grouped form is a different list: the
five button* tokens, the six chart* series colours, the
eight hl* syntax colours, borderWidth,
transitionDuration and the four type metrics
(lineHeightBody, lineHeightHeading,
letterSpacingHeading, headingTextTransform). Those 25
tokens have no group to live in, so they only reach the host through the flat
shape — see
tokens with no $theme route.
A name: base does not carry the theme's CSS personality
When you start from shadcn, mui,
heroui, signal or soft, the generated statement begins
$theme({ name: "…" }). That copies the theme's
token values, but not its extra stylesheet block —
MUI's uppercase tabs and borderless Paper, HeroUI's dimming hover and
offset focus ring, shadcn's 3px focus halo. Those are gated on the data-rui-theme
marker, which only the host theme attribute and
setTheme() write. For the full look, set the theme on the host
and paste the generated overrides on top. Details:
Per-response vs host theme.
Two more things the panel leaves alone. colors.link /
colors.linkHover are optional and derived from the accent, so they
have no base value to show; add them by hand if your accent is too light to read
as link text. And RTL is not a token at all — use the dir
attribute on <aktion-app>.
Next
Themes & customization
Every token group, the built-in themes, and the flat vs grouped token shapes.
Read the reference → ReferenceComponent catalog
Every component and prop, with live previews that follow the active theme.
Browse components → Try itPlayground
Paste your $theme({…}) and a full program into the live editor.