UX-DSL
XS0px

Runtime API

postcss-uxdsl/ds-runtime, called for real on this page.
Nothing below is a description of a call: each panel runs the exported function and shows what it returned.

The theme this site applied

The site initializes the runtime once, in ThemeContext, with applyTheme(themes.default, { replace: true, styleId: 'uxdsl-ssr-theme' }) — the override it was built with — and applies the other named themes the same way when you pick one in the header. The calls here only read that state: getAppliedTheme() returns the applied override, subscribeTheme(listener) is notified after each successful application, and getPalette('primary-main') reads the computed custom property.

This site, right now

Theme selected in the header
default
getAppliedTheme() — families in the applied override
{} (not initialized yet)
getAppliedTheme().palette.primary.main
getPalette('primary-main') — the computed custom property

The two can differ: the override holds the light value, and in dark mode the stylesheet applyTheme generated switches primary-main to modes.dark's — which is what getPalette reads.

subscribeTheme(listener)

No application yet since this page loaded. Switch the theme in the header: each successful applyTheme notifies this listener.

Calls that change state run in a sandbox

applyTheme, resetTheme and loadPersistedTheme manage one stylesheet per document; the per-token setters (updatePalette, updateColor, updateSpacing, updateBreakpoint) write inline custom properties and rewrite compiled media queries. On this page they would compete with ThemeContext, so they run in the frame below: a page compiled with this site's default theme (by the real compiler, at build time), with its own document and its own copy of the runtime. Run the steps in order, watch the frame and the report, and reload the sandbox to undo everything.

Two results are worth reading closely, because they are the honest edges of the old API rather than bugs in this page. After updatePalette, a later applyTheme returns ok: true and the color does not change: the inline value beats any stylesheet (this site's ThemeContext clears those inline values after each application for exactly that reason). And after updateBreakpoint('md', 900), getBreakpoints() says 900 while getAppliedTheme() still says 768: the legacy API rewrote the compiled rules, not the theme, and applyTheme itself refuses to move a threshold (UXD_THEME_STRUCTURE) — moving one is a rebuild.

loadPersistedTheme is always called here with the lab's own key and migrateLegacy: false. A default call migrates, and then deletes, the four pre-beta.6 storage keys — which this site's older demos still write.

Theme API

  1. Before the project theme was applied once: refused, nothing moves.
  2. Initialize with the override the sandbox was compiled with (this site's default theme).
  3. A value change: applied, and saved under the lab's own key.
  4. Moving a threshold changes what the compiler emitted: refused with UXD_THEME_STRUCTURE.
  5. Back to the override it was initialized with — not the packaged base.
  6. The saved override comes back, validated like any patch.
  7. What is applied now, as a copy.
  8. Reset and forget the saved override.

Per-token setters (pre-beta.6)

  1. Writes an inline custom property on <html>.
  2. Reads the computed value back.
  3. Conflict: ok: true, but the swatch stays pink — the inline value beats the stylesheet. (Initialize with the second step first.)
  4. Removes the inline value; the stylesheet shows again.
  5. Only color(gray-300) consumers follow.
  6. density(4) is space(5) at this width, so the Density box grows; the space(4) box does not.
  7. Rewrites the compiled media queries: at 820px the layout drops below md. The theme stylesheet applyTheme manages is not rewritten, so Density still switches at 768.

What the sandbox reports

Calls, results, and what subscribeTheme / subscribe heard

Run a step. Each call's return value is shown as it came back.

Resolution, engines and fonts

These functions are pure: they take a theme and return a value, so they run on this page against the active theme. resolveTheme is the one place an effective theme is built (the base with an override merged over it); buttonDeclarations, inputDeclarations and resolveTypographyRole are what @ds-button, @ds-input and @ds-typo expand to — the compiler calls the same functions; googleFontsImportUrls and encodeGoogleFontFamily build the Google Fonts @import both the compiler and generateThemeCss emit.

resolveTheme(override) and getDefaultTheme()

Effective palette.primary (15 families in the resolved theme)
VariantresolveThemeFromgetDefaultTheme
main#0f766eyour override#7e22ce
light#a855f7base#a855f7
dark#581c87base#581c87
contrast#ffffffbase#ffffff

Override only main and dark/contrast come from the base: the same merge uxdsl theme --diff labels leaf by leaf (see the CLI page).

buttonDeclarations · inputDeclarations · resolveTypographyRole

What @ds-button(contained) emits for the active theme:

base
paddingvar(--uxdsl__surface__contained-padding)
border-radiusvar(--uxdsl__surface__contained-radius)
backgroundvar(--uxdsl__surface__contained-bg)
colorvar(--uxdsl__surface__contained-color)
bordervar(--uxdsl__surface__contained-border)
box-shadowvar(--uxdsl__surface__contained-shadow)
state: hover
backgroundvar(--uxdsl__button__contained-hover-bg)
colorvar(--uxdsl__button__contained-hover-color)
state: selected
backgroundvar(--uxdsl__button__contained-selected-bg)
colorvar(--uxdsl__button__contained-selected-color)

googleFontsImportUrls · encodeGoogleFontFamily

The active theme's fonts.google, as the @import URLs the compiler and generateThemeCss both emit:

  • https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap

encodeGoogleFontFamily → Noto+Sans+JP:wght@400;700