Style (asset type)
A style is a UI design-token bundle: colour palette, spacing scale, typography pairs. Styles cascade through the UI theme system — engine default < per-screen style < per-panel style. Authoring a…
When to use one
- You're branding a UI surface (game theme, editor theme, dialog theme) and want a named token set widgets pick up automatically.
- You want a swappable theme — light vs dark, normal vs accessibility contrast.
- You want designers to edit tokens (
colors.primary,spacing.md) without touching widget code.
If you need per-widget overrides, those go inline on the widget, not
in a style. If you need shader-driven looks, that's a .shader +
.material.
Where it lives
- Source:
/zero/source/.../<name>.style/ - Identity:
<name>(the.stylesuffix strips). - Folder shape:
init.luau(orinit.lua) — exports the token table. Required.README.md— instance documentation. Required.
How to create one
asset.create("style", "<name>")
-- Creates: /zero/source/styles/<name>.style/
-- init.luau (token scaffold: color / spacing / font)
-- README.md (instance README template)
How it operates
- Registration. Writing
init.luauinto a.style/folder indexes the style with the UI theme system. - Token shape. The exported table is hierarchical:
color.<name>—{r, g, b, a}tables in linear sRGB.spacing.<name>— discrete pixel values.font.<name>—{ family, size }pairs. Custom token groups beyond the canonical three are allowed; the UI theme system passes them through to widgets that ask for them.
- Cascade. Styles cascade through the theme system: engine default → per-screen style → per-panel style. A widget reads the most-specific token in scope.
- Application.
ui.applyStyle("<name>")sets the currently-active style globally.screen:setStyle("<name>")scopes a style to one screen. Per-panel style is set on the panel widget. - Hot reload. Editing
init.luaureloads the style; widgets under it re-pick tokens on the next layout pass.
Discovery
asset.list("style")— every registered style.asset.inspect("<name>")— token surface, source, this type README.cat /zero/source/<name>.style— same summary.
Authoring conventions
- Use
linear-sRGB(0..1 floats) for every colour, not 0..255 bytes. The renderer expects linear values. - Name tokens semantically (
color.primary,color.danger,spacing.gutter), not by visual value (color.blue,spacing.eight). Semantic names survive theme swaps. - Keep token names stable. Widgets reference tokens by name — renaming a token forces every consumer to update.
- Document
light/darkvariants under separate.style/folders with paired names (game.style,gameDark.style) rather than switching values within one style.
Common pitfalls
- sRGB vs linear. UI looks washed-out or oversaturated → check you're using linear-sRGB floats, not 0..255 bytes.
- Token-name typos. Misnamed tokens silently miss the cascade and widgets fall back to engine defaults.
- Missing tokens. A widget asking for
color.warnwhen the style doesn't define it gets the cascade fallback. Inspect the style to confirm the token surface.
Related types
.component—UiPaneland other widget components consume styles..material/.shader— for 3D surface looks (different cascade system)..package— to ship styles + components together as a theme package.