Theming
Every colour, radius, spacing and shadow comes from tokens. Pick a base gray, an accent colour and a radius — every component, native ArkUI ones included, updates live.
Presets and accents
Built-in presets match shadcn v4 base colours: neutral (default), zinc, slate, stone, gray. Accents are layered on top and only recolour primary / ring / sidebar-primary: blue, green, orange, red, rose, violet, yellow.
SparkUI.themes.usePreset('zinc'); // base gray (keeps accent and overrides such as radius)
SparkUI.themes.useAccent('violet'); // accent; 'none' = monochrome shadcn default
SparkUI.themes.setMode('dark'); // 'light' | 'dark' | 'system'
SparkUI.themes.toggleDark();
SparkUI.themes.setVariable('--radius', '0.75rem');Try it in the web preview (the picker applies to every preview on the site; values are generated from Presets.ets):
Approximate web preview — the HarmonyOS rendering is the reference.
Base grays only shift the hue of neutrals (backgrounds, borders, muted text) — subtle by design, exactly like shadcn. Accent colours change primary and ring.
Loading shadcn / tweakcn themes
A SparkUI theme file is a CSS subset: :root {}, .dark {}, @size(compact|medium|expanded|large) {}, --var: value; and comments. shadcn / tweakcn exports paste as-is: @theme, @layer, @import, @custom-variant, other selectors and non-custom properties are recognised and skipped with an info diagnostic. oklch, hsl, rgb and hex are converted precisely.
:root {
--radius: 0.5rem;
--primary: oklch(0.546 0.245 262.881);
--primary-foreground: oklch(0.97 0.014 254.604);
}
.dark {
--primary: oklch(0.623 0.214 259.815);
}
@size(compact) {
:root { --radius: 0.375rem; }
}const r1 = SparkUI.themes.loadString(cssText); // CSS subset or JSON (auto-detected)
const r2 = SparkUI.themes.loadRawfile('themes/brand.css'); // resources/rawfile
const r3 = SparkUI.themes.loadFile(sandboxPath);
const r4 = await SparkUI.themes.loadUrl('https://…/theme.css'); // needs ohos.permission.INTERNET
if (!r1.ok) {
r1.diagnostics.forEach((d: ThemeDiagnostic) => console.warn(d.message));
}
SparkUI.themes.exportCss(); // the effective theme (preset + overrides)Loading never throws: missing or invalid tokens fall back to the underlying preset and problems come back as diagnostics (error / warning / info).
Status colours and component tokens
- Status colours are real semantic tokens:
--success,--warning,--infoand their-foreground. - The global knob
--border-widthcontrols the border of every bordered component. - Component tokens are named
--<component>-<property>:--card-background,--button-radius,--button-outline-background,--button-height-sm… Unset tokens fall back to the component's shadcn recipe. - Override a single instance with the
tokensparam:
Approximate web preview — the HarmonyOS rendering is the reference.
- Theme-wide, set them like any other variable (
setVariable, or atheme.cssloaded withloadString). Status badges and alerts read the semantic status tokens:
Approximate web preview — the HarmonyOS rendering is the reference.
Native components
SparkProvider mirrors the tokens into the system theme (WithTheme / ThemeControl), so native Toggle, TextInput & co. follow the accent and the colour mode too.