Skip to content

feat(examples-chat): app-wide Light/Dark color scheme toggle#288

Merged
blove merged 1 commit into
mainfrom
claude/theme-toggle-app-wide
May 13, 2026
Merged

feat(examples-chat): app-wide Light/Dark color scheme toggle#288
blove merged 1 commit into
mainfrom
claude/theme-toggle-app-wide

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 13, 2026

Summary

The smoke-test demo previously hardcoded dark mode (<html data-ngaf-chat-theme="dark"> plus literal #0f1116/#e6e9ef in styles.css). The palette's existing A2UI Theme dropdown only restyled the <a2ui-surface> inside the chat composition, so switching it to default-light left the page background and chat composition unreadably dark.

This PR adds a runtime app-wide Light/Dark color-scheme toggle above the Theme dropdown. A single selection drives:

  • demo page bg/text via data-color-scheme on <html> (CSS custom props in styles.css)
  • chat lib internals via data-ngaf-chat-theme on <html>
  • base A2UI theme via data-themeonly when the dropdown is on a default-* preset. Material picks are preserved since the user explicitly opted in.

To avoid FOUC on reload, a tiny pre-bootstrap inline script in index.html reads the persisted scheme from localStorage and sets the two attrs synchronously before any stylesheet loads. The DemoShell effect takes over once Angular bootstraps.

Files

  • examples/chat/angular/src/styles.css — body bg/text now use var(--demo-page-bg)/var(--demo-page-text); html[data-color-scheme="light"] override block
  • examples/chat/angular/src/index.html — drops hardcoded data-ngaf-chat-theme="dark"; adds pre-bootstrap script
  • examples/chat/angular/src/app/shell/palette-persistence.service.ts — extends PaletteState with colorScheme
  • examples/chat/angular/src/app/shell/demo-shell.component.tscolorScheme signal, colorSchemeOptions, onColorSchemeChange, effect that syncs data-color-scheme + data-ngaf-chat-theme and (conditionally) the A2UI theme
  • examples/chat/angular/src/app/shell/demo-shell.component.html — new <chat-debug-segmented> above the Theme <chat-debug-select>

Test plan

  • nx test chat passes
  • nx build chat passes
  • nx lint chat clean
  • nx build examples-chat-angular passes
  • Manual: open /embed — palette shows Light/Dark segmented above Theme; default is Dark
  • Manual: switch to Light — page bg flips to white, chat composition updates, A2UI dropdown auto-switches default-darkdefault-light
  • Manual: pick material-light then toggle scheme — Material stays selected (no auto-sync)
  • Manual: reload — scheme persists, no flash of light/dark before bootstrap

The smoke-test demo previously hardcoded dark mode in index.html and
styles.css, while the palette's A2UI Theme dropdown only restyled the
<a2ui-surface> inside the chat composition. Toggling that dropdown to
default-light left the page bg and chat composition unreadably dark.

This adds a runtime app-wide color-scheme toggle (Light/Dark) above
the existing Theme dropdown. The selection drives:

- the demo page bg/text via `data-color-scheme` on <html>
- the chat lib's internals via `data-ngaf-chat-theme` on <html>
- the base A2UI theme via `data-theme` — but only when the dropdown
  is on a default-* preset. Material picks are left alone since the
  user explicitly opted in.

A pre-bootstrap inline script in index.html applies the persisted
scheme before stylesheets load to avoid FOUC; the DemoShell effect
takes over once Angular bootstraps.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 13, 2026

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

Project Deployment Actions Updated (UTC)
cacheplane Building Building Preview, Comment May 13, 2026 3:34am

Request Review

@blove blove merged commit 55951ce into main May 13, 2026
13 of 14 checks passed
blove added a commit that referenced this pull request May 13, 2026
@cacheplane/partial-markdown@0.3 does not flush trailing text on
finish() unless the buffer ends with a newline. Plain LLM responses
typically omit the trailing newline, so the parser produced a document
with zero children — the assistant bubble shell rendered but the
message text was missing entirely.

Reproduce on main: send 'Say hello in one sentence.' to gpt-5-mini.
Backend logs show success (1.8s); agent.messages() carries 'Hello — nice
to meet you!'; the DOM shows the bubble structure (checkpoint marker,
action buttons) but no text.

Fix: push a sentinel newline before calling finish() in both branches
of the root() computed (content-changed-then-flush and streaming-flipped-
without-new-content). The newline only ever exists inside the parser
buffer; the original content() signal is unchanged.

Two new regression tests cover plain text without trailing newline in
both branches.

Found while walking the smoke checklist post-#288.
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