Theme engine
A generated OKLCH token layer for runtime customization. The engine switches mode,
base gray, primary, radius, font, and style recipe through data-zits-*
attributes, so components keep using the same utility classes.
Overview
ThemeStylesheet.Generate() writes a committed zits-theme.css
static asset from C#. The CSS is deterministic, culture independent, and drift guarded
by unit tests. It composes the dimensions as small attribute-keyed blocks instead of
generating one class for every possible combination.
Generated
C# StringBuilder output, committed as a static web asset.
Runtime
A scoped service writes attributes and persists JSON to localStorage.
Scoped
Any subtree can carry its own full theme, including forced light or dark.
Live switcher
Open the switcher and pick a dimension. The whole page changes because the selected
values are written to <html>. Reset removes the runtime attributes and
returns this docs site to its signal-red token theme.
The panel also exposes the resolved :root and .dark CSS export.
Card
Surface tokens
Secondary
Recipe tokens
Primary
Brand token
Install
Two paths, depending on how you consume zits/ui. Package mode references the
Zits.Ui package and serves the engine assets from its static web assets.
Vendored mode copies them into your own project with navius add theme.
Package mode
AddZitsUi() ships with the package and registers the theme service.
<PackageReference Include="Zits.Ui" Version="0.3.0-preview.5" />builder.Services.AddNavius();
builder.Services.AddZitsUi();<script src="_content/Zits.Ui/zits-theme-init.js"></script>
<link href="_content/Zits.Ui/zits-ui.css" rel="stylesheet" />
<link href="_content/Zits.Ui/zits-theme.css" rel="stylesheet" />Vendored mode
There is no AddZitsUi() without the package: register the vendored
ZitsThemeService directly, and call AddNavius() for the
overlay services its switcher popover uses. The assets copy into your wwwroot,
so they serve from the app root.
navius add themebuilder.Services.AddNavius(); // brain overlay + keyboard services
builder.Services.AddScoped<ZitsThemeService>(); // the vendored theme service<script src="/zits-theme-init.js"></script>
<link href="/zits-ui.css" rel="stylesheet" />
<link href="/zits-theme.css" rel="stylesheet" />Scoped themes
ZitsThemeScope renders a normal container with the six theme attributes.
Custom properties resolve at the element that uses them, so nested cards, buttons, and
form controls pick up the scoped theme without component changes.
Forced light
This box stays light inside a dark page.
Forced dark
This box stays dark inside a light page.
CSS export
ThemeStylesheet.GenerateCss(theme) resolves one selection to a standalone
:root and .dark block. Use it when you want to stop depending on
the runtime switcher and bake the chosen design back into your own token file.
var theme = new ZitsTheme(
ZitsThemeMode.System,
Base: "neutral",
Primary: "blue",
Radius: "md",
Font: "system",
Style: "standard");
var css = ThemeStylesheet.GenerateCss(theme);