Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·part ofmodule zui.module·originates fromworld 07158574-5…

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 re…

byzero-proxy @ DESKTOP-DB3UJOJ·posted 2mo ago
What it does

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.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

ZuiTheme Module 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 existing demos. The cascade has moved out of Rust into Luau. Themes are first-class Luau modules that return `{ name, tokens, styles }`. This module's `register` / `load` / `activate` functions resolve the `$variable` cascade in pure Luau (with cycle detection — strictly stronger than the silent-on-cycle Rust resolver it replaces) and push flat values to the engine via `ui.registerTheme(name, flatTable)`. Consumers: local Theme = require("modules.deprecated.zui.theme") Theme.load("dark") -- require + register Theme.activate("dark") -- thin wrapper over ui.setTheme local view = Theme.with({ accent = "#ff0" }) -- override view

resolveToken(name: string) → any

Internal: resolve a single token by name. Probes the engine first (`ui.getToken`) so a loaded engine theme overrides the defaults.

argtypedescription
namestring

makeView(overrides: TokenMap?) → ThemeView

Internal: build a read-only view that proxies token reads through `overrides → module functions → engine/defaults`. Writes throw. Forward-declared so it can reference M before M is fully populated.

argtypedescription
overridesTokenMap?

__index(_: ?, key: ?) → void

argtypedescription
_?
key?

__newindex( ) → void

with(overrides: TokenMap?) → ThemeView

Build a read-only theme view that overlays the given overrides on top of the engine-or-defaults token map. Module functions are exposed alongside tokens so the view doubles as the namespace.

argtypedescription
overridesTokenMap?Optional table of `{ [tokenName] = value }` overrides.

examples

local view = Theme.with({ accent = "#ff0" })
local view = Theme.with(nil)  -- defaults only

defaults( ) → TokenMap

Return the raw fallback token map shipped with this module. Used by tests / introspection; not part of the cascade.

examples

local d = Theme.defaults()

tokenNames( ) →

Return the sorted list of token names shipped with this module. Useful for theme editors / token pickers.

examples

for _, n in ipairs(Theme.tokenNames()) do print(n) end

resolve(theme: any) →

Resolve `$variable` references in a theme table and return the flat `{ name, tokens, styles }` shape the engine consumes. Pure function — used by `register` and exposed for tests.

argtypedescription
themeanyA theme table with `name`, `tokens`, `styles`.

examples

local res, err = Theme.resolve({ name = "dark", tokens = {...} })

register(name: string, theme: any) →

Register a theme with the engine under `name`. Walks the theme's tokens + styles, resolves every `$variable` reference (with cycle detection), and pushes flat values to the active `ThemeRegistry`.

argtypedescription
namestringThe name to register the theme under.
themeanyThe theme table `{ tokens, styles }` — `name` is overridden by the caller-supplied `name`.

examples

local ok, err = Theme.register("dark", themeTable)

load(name: string) →

Convenience: `require("@builtin::themes." .. name)` then register. Built-in themes (dark, light, debug) live at `src/lua/lib/themes/<name>.module/init.luau`.

argtypedescription
namestringThe built-in theme name to require and register.

examples

Theme.load("dark")

activate(name: string) → boolean

Activate a registered theme. Thin wrapper over `ui.setTheme(name)` for symmetry with `register` / `load`.

argtypedescription
namestringThe registered theme name to activate.

examples

Theme.activate("dark")
⌬ Types
TokenMap = ZuiThemeTokensStyleMap = { [string]: { [string]: any } }Theme = { name: string?, tokens: ZuiThemeTokens?, styles: StyleMap? }ResolvedTheme = { name: string, tokens: ZuiThemeTokens, styles: StyleMap }ThemeView = any -- read-only metatable proxy over the token map

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

7items
·
other · born here
▤file
▲ 0↑ born
▣
module · born here
❒asset
# cascade Pure-Luau `$variable` cascade resolver for theme tokens and styles. Walks a theme table's tokens and styles, expands every `$tokenName` reference into a literal value with cycle detection, and returns a flat result. Used by `Z.theme.register` so the engine receives fully-resolved `(token, value)` and `(selector, prop, value)` pairs — no runtime variable indirection. Cycle detection surfaces broken theme inputs as structured `register` errors instead of silently leaving `Variable(name)` in place and producing garbage colors. ## Exports - `M.resolveValue(value, tokens, visited, order) -> (any, string?)` — single-value resolver. Exposed for tests; not part of the typed surface. - `M.resolveTokens(theme: any) -> (TokenMap?, string?)` — flatten `theme.tokens`. Returns `(nil, errMsg)` on first cycle / unknown reference. - `M.resolveStyles(theme: any, resolvedTokens: any) -> (StyleMap?, string?)` — flatten `theme.styles` against pre-resolved tokens. Types: - `TokenMap = { [string]: any }` - `StyleMap = { [string]: { [string]: any } }` - `Theme = { tokens: TokenMap?, styles: StyleMap? }` ## Usage ```luau local Cascade = require("@builtin::modules.zui.theme.cascade") local tokens, err = Cascade.resolveTokens(theme) if err then error(err) end local styles, err2 = Cascade.resolveStyles(theme, tokens) if err2 then error(err2) end -- `tokens` and `styles` now contain no `$variable` strings. ``` ## Notes - Pure module — no engine calls, no module state. Safe to invoke during any phase (boot, test, runtime). - Error messages include the offending token / selector / prop so cascade failures are diagnosable from the structured error alone. - `resolveStyles` resolves against pre-flattened `resolvedTokens` (not raw `theme.tokens`) so chained references (`$a → $b → c`) are already collapsed by the time style values are walked. - Numbers, booleans, and arrays pass through unchanged — only strings beginning with `$` are treated as references.
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.