Skip to content

feat(chat): A2UI theme presets — default-light, material-dark, material-light (Pass 3)#235

Merged
blove merged 1 commit into
mainfrom
claude/a2ui-theme-presets
May 10, 2026
Merged

feat(chat): A2UI theme presets — default-light, material-dark, material-light (Pass 3)#235
blove merged 1 commit into
mainfrom
claude/a2ui-theme-presets

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 10, 2026

Summary

Pass 3 of the A2UI theming track. Ships four CSS preset files consumers `@import` to override the ~50 internal `--a2ui-*` tokens declared at `` `:host` (Pass 2b) at the `:root` level.

Presets

  • `themes/default-dark.css` — lib defaults, explicit (no-op import for symmetry/docs)
  • `themes/default-light.css` — neutral light palette with blue accent; off-white surface, softer elevation
  • `themes/material-dark.css`Material Design 3 dark color tokens (purple primary, M3 surface tokens). No `@angular/material` runtime dep — pure CSS custom properties.
  • `themes/material-light.css` — M3 light palette

Each preset declares only the tokens that differ from the lib's `:host` defaults — typically the 13-token color block, plus elevation softening on light themes.

Wiring

  • `libs/chat/package.json` `exports` map: `./themes/*.css` entry per preset
  • `libs/chat/ng-package.json` `assets`: copies `src/themes/*.css` to `dist/libs/chat/themes/` at build time. Verified `dist/libs/chat/themes/` contains all 4 preset files post-build.

Composition with agent overrides

The agent's `beginRendering.styles.primaryColor` continues to override `--a2ui-primary` per surface (host inline-style binding, highest specificity), so consumer-imported preset + agent-driven override compose cleanly: consumer chooses the palette baseline, the agent can per-surface tweak the primary color.

Documentation

`libs/chat/README.md` gains an "A2UI surface theming" section documenting:

  • The two agent-driven knobs (v1 wire format)
  • The four built-in presets with import snippets
  • The full ~50-token vocabulary for custom themes

Test plan

  • `nx run-many -t test,lint,build -p chat` — all green
  • `dist/libs/chat/themes/{default-dark,default-light,material-dark,material-light}.css` exist post-build
  • After merge: import each preset into a consumer's global stylesheet, verify visible reskin (color palette, surface, button accent)

Open follow-up (deferred)

A demo-side preset switcher dropdown (palette "Theme: default-dark | default-light | material-dark | material-light") would let users live-test presets without editing CSS. Out of Pass 3 scope; tracked for future iteration.

🤖 Generated with Claude Code

…al-light (Pass 3)

Pass 3 of the A2UI theming track. Ships four CSS preset files
consumers @import to override the ~50 internal --a2ui-* tokens
declared at <a2ui-surface> :host (Pass 2b) at the :root level:

- themes/default-dark.css   — lib defaults, explicit (no-op import for
                              symmetry/docs)
- themes/default-light.css  — neutral light palette with blue accent;
                              off-white surface, softer elevation
- themes/material-dark.css  — Material Design 3 dark palette (purple
                              primary, M3 surface tokens). Color values
                              from m3.material.io. No @angular/material
                              runtime dep — pure CSS custom properties.
- themes/material-light.css — M3 light palette

Each file declares only the tokens that differ from the lib's :host
defaults — typically the 13-token color block, plus elevation
softening on light themes and shape adjustments where they differ.

Wired into the package via:
- libs/chat/package.json `exports` map: ./themes/*.css per preset
- libs/chat/ng-package.json `assets`: copies src/themes/*.css to
  dist/libs/chat/themes/ at build time

The agent's beginRendering.styles.primaryColor continues to override
--a2ui-primary per surface (host inline-style binding, highest
specificity), so consumer-imported preset + agent-driven override
compose cleanly.

README.md gains an "A2UI surface theming" section documenting the
agent-driven knobs (v1 wire format), built-in presets, and the full
~50-token vocabulary for custom themes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cacheplane Ready Ready Preview, Comment May 10, 2026 3:40pm

Request Review

@blove blove merged commit ca01c10 into main May 10, 2026
14 checks passed
blove added a commit that referenced this pull request May 10, 2026
Adds a 6th palette dropdown that switches A2UI theme presets at
runtime by toggling `data-theme` on the document root. The global
stylesheet keys scoped `--a2ui-*` overrides off this attribute.

Four presets, mirroring the lib-side files shipped in PR #235:
- Default dark   (lib's :host defaults; data-theme attr set but no
                  override block needed — the unset state)
- Default light  (neutral light, blue accent, off-white surface)
- Material dark  (M3 purple primary on dark surface)
- Material light (M3 purple primary on near-white surface)

Inline-themes-in-styles.css approach (vs. dynamic <link> swap)
sidesteps the workspace-vs-published-path resolution complexity:
each theme's :root override block lives in
examples/chat/angular/src/styles.css gated by `data-theme="..."`
attribute selector. Mirrors content from libs/chat/src/themes/*.css.

Wiring:
- demo-shell: `theme` signal (default 'default-dark', persisted via
  palette-persistence under key 'theme'); `effect()` reflects current
  signal value onto `<html data-theme>` so the global stylesheet's
  `:root[data-theme=...]` rules activate. Initial mount reads from
  persistence and the effect immediately syncs the attribute.
- control-palette: new `theme` + `themeOptions` inputs and
  `themeChange` output; new `<select>` next to Gen UI.
- palette-persistence: `theme` added to PaletteState type.

Verified live: switching the dropdown updates --a2ui-primary
computed style on document root in real time:
- default-dark: lib :host default (--a2ui-primary inherited from
                surface component, computed at root = empty/inherit)
- material-dark: --a2ui-primary = #D0BCFF (M3 purple)
- material-light: --a2ui-primary = #6750A4 (M3 light purple)
- data-theme attribute on <html> updates synchronously

The agent's beginRendering.styles.primaryColor still wins per surface
(host inline-style binding, highest specificity), so consumer-chosen
theme + agent-chosen primary color compose: theme decides palette
baseline, agent can per-surface override.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant