Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

theme

Theme tokens for zui (Layer 2). Reads through ui.getToken(name) first so a loaded engine theme propagates automatically; falls back to in-module defaults that cover every named color used by the demos. Also owns the Luau-side $variable cascade — register / load resolve references end-to-end (cycle-detected) and push flat values to ui.registerTheme.

Exports

  • M.with(overrides: TokenMap?) -> ThemeView — read-only view with overlays on top of engine/defaults.
  • M.defaults() -> TokenMap — raw default token map (same reference each call).
  • M.tokenNames() -> { string } — sorted list of shipped token names.
  • M.resolve(theme: any) -> (ResolvedTheme?, string?) — flatten a theme table ($var → literal). Returns (nil, errMsg) on failure.
  • M.resolveTokens(theme) -> (TokenMap?, string?) — re-export from cascade.
  • M.resolveStyles(theme, tokens) -> (StyleMap?, string?) — re-export from cascade.
  • M.register(name: string, theme: any) -> (boolean, string?) — resolve and push to ui.registerTheme.
  • M.load(name: string) -> (boolean, string?) — require @builtin::themes.<name> and register it.
  • M.activate(name: string) -> boolean — thin wrapper over ui.setTheme(name).
  • M.default: ThemeView — module-level token view with no overrides.

Types:

  • TokenMap = { [string]: any }
  • StyleMap = { [string]: { [string]: any } }
  • Theme = { name: string?, tokens: TokenMap?, styles: StyleMap? }
  • ResolvedTheme = { name: string, tokens: TokenMap, styles: StyleMap }
  • ThemeView — read-only metatable proxy; writes throw.

Usage

local Theme = require("@builtin::modules.zui.theme")

Theme.load("dark")          -- require + register the built-in dark theme
Theme.activate("dark")      -- ui.setTheme("dark")

local view = Theme.with({ accent = "#ff0" })
print(view.accent)          -- "#ff0"
print(view.bg)              -- engine token or default

Notes

  • register overrides theme.name with the caller-supplied name so listThemes() / setTheme(name) find it under the requested key (mirrors the pre-Phase-4 #942 fix).
  • The cascade is cycle-detected — broken inputs surface as structured (false, errMsg) returns instead of silently producing garbage colors.
  • M.default is built at module-load time, after M is fully populated, so its function-fallback __index resolves correctly.
  • ThemeView writes raise — use Z.themeWith({...}) to get an overlay view rather than mutating the existing one.