Skip to content

fix(chat): critical message-rendering bugs (0.0.4)#161

Closed
blove wants to merge 38 commits into
mainfrom
claude/dazzling-dewdney-887eac
Closed

fix(chat): critical message-rendering bugs (0.0.4)#161
blove wants to merge 38 commits into
mainfrom
claude/dazzling-dewdney-887eac

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 1, 2026

Summary

Fresh-install smoke test against the just-published @ngaf/chat@0.0.3 surfaced three critical UX bugs that shipped:

  1. Message content never rendered. chat-message used `` inside `@switch @case` blocks; Angular content projection is resolved at view-creation, so projected text/templates never reached the per-role slots. Result: empty user bubbles, empty assistant bodies — chat looked broken end-to-end.

  2. Empty state had no default content and didn't hide. `[chatEmptyState]` slot had no fallback, and the `[hidden]` attribute was overridden by `display: flex`, so the empty state stayed visible after messages arrived.

  3. Input textarea didn't clear on submit. The ngModel proxy getter/setter pattern doesn't reactively re-read on signal change.

Fixes

  • chat-message: single root-level `` + role-driven CSS class. Caret + controls visibility moved to host-attribute selectors (`data-role` / `data-current` / `data-streaming`).
  • chat composition: empty state has default `How can I help? / Ask anything to get started.` fallback + explicit `.chat-empty[hidden] { display: none; }`.
  • chat-input: switch from `messageTextProxy` getter/setter to signal-native `[ngModel]="messageText()" (ngModelChange)="messageText.set($event)"`.

Validation

Validated end-to-end on a fresh `ng new` Angular 21 app with no Tailwind, no PostCSS, no global stylesheet:

  • Embedded mode renders user bubble + streaming markdown assistant correctly
  • Popup mode opens with full conversation; close button works
  • Empty state shows default content; hides cleanly when messages arrive
  • Input clears on submit

Known issues (deferred)

  • `<chat-sidebar [pushContent]="true">`: panel positioning under push-content mode looks off in some viewports; needs follow-up.
  • License-warning console spam (6 logs per page load) — module dedupe Set isn't deduplicating across what appear to be separate evaluation contexts.
  • `marked` peer is documented as optional but the fallback is unusable raw markdown text. Consider making it required.

Test plan

  • All chat unit tests pass
  • Fresh-install smoke app renders user/assistant messages, popup mode, empty state
  • Lint passes (no errors)
  • CI green
  • Tag v0.0.4 to fire publish workflow

🤖 Generated with Claude Code

blove and others added 30 commits May 1, 2026 10:10
The 0.0.2 publish workflow run failed with 'error retrieving identity
token' on @ngaf/licensing and @ngaf/partial-json, and a 404 on
@ngaf/a2ui. Root cause: actions/setup-node@v6.3.0 with node-version: 22
ships npm 10.9.2, which has partial OIDC code paths but doesn't fully
implement the trusted-publishing flow against npm registry's OIDC
endpoint.

npm 11.5.1+ is required for trusted publishing. Adding 'npm install -g
npm@latest' before the publish step bumps the runner to a current
release.

Sources:
- https://philna.sh/blog/2026/01/28/trusted-publishing-npm/
- npm/cli#8730
- https://docs.npmjs.com/trusted-publishers/

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Verified against a fresh-install consumer of @ngaf/chat@0.0.2: without
Tailwind configured (and without `@source "../node_modules/@ngaf/chat"`),
ChatComponent's utility classes (flex, gap-3, max-w-[75%], md:flex, ...)
are tree-shaken away and the chat collapses to a column of unstyled
full-width blocks. The library does not ship a precompiled stylesheet,
so this is a hard consumer-side requirement.

Surface it explicitly:
- Quickstart gets a Tailwind setup step between install and
  provider config.
- Installation Requirements step calls out Tailwind v4 alongside
  Angular 20+ and Node 18+.
- Tailwind CSS section is rewritten with concrete steps (postcss
  config, @import, @source) rather than just an `npm install` line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Design for production-ready chat UI overhaul: asymmetric message
pattern (user bubble + assistant inline), three layout modes
(embedded, popup, sidebar), shared chat-trace primitive driving
tool calls / subagents / timeline, complete Tailwind removal with
encapsulated component styles + optional global chat.css.

Settled architecture decisions:
- Three separate compositions over a unified mode-switching one.
- Hybrid styling: component-encapsulated + CSS vars + optional
  global stylesheet for deep overrides.
- In-place rewrite of <chat>; coordinated breaking-change PR
  updates all 19 cockpit demos + libs/example-layouts + website
  docs in one shot. Ships as 0.0.3 (patch-only policy).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
56-task plan covering tokens (Phase 1), new primitives (Phase 2),
existing primitive rewrites (Phase 3), trace-based card rewrites
(Phase 4), top-level compositions (Phase 5), debug + interrupt
panel (Phase 6), library cleanup + 0.0.3 bump (Phase 7),
example-layouts (Phase 8), 19 cockpit demos (Phase 9), website
docs (Phase 10), and verification + PR (Phase 11).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renames the ChatMessagesComponent primitive to ChatMessageListComponent
with selector chat-message-list, adds dedicated host styles, and updates
all consumers (chat composition, chat-debug composition, public-api).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces Tailwind-based layout + inline avatar markup with CSS-custom-property
shell layout; wraps each message role in <chat-message> inside the per-role
templates; adds <chat-tool-calls> and <chat-subagents> inside the assistant
wrapper; introduces prevRole() helper for spacing context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace Tailwind utility classes with hand-written BEM CSS, rename all --chat-* tokens to --ngaf-chat-*, and add CHAT_HOST_TOKENS to styles array.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all Tailwind utility classes with hand-written BEM CSS, rename --chat-* tokens to --ngaf-chat-* across all 8 debug component files, and add CHAT_HOST_TOKENS to every styles array. Inline markdown styles in chat-debug updated to use new token names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
blove and others added 8 commits May 1, 2026 14:19
…ration)

- cockpit-chat-input: ChatMessagesComponent → ChatMessageListComponent, <chat-messages> → <chat-message-list>, --chat-* → --ngaf-chat-*
- cockpit-chat-messages: same rename + token migration; e2e selector chat-messages → chat-message-list
- cockpit-chat-theming: THEMES map and template updated to --ngaf-chat-* token names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove Tailwind requirement, update peer deps, add optional chat.css
import, rewrite quickstart to 3-step no-setup flow, and rewrite theming
guide with full --ngaf-chat-* token table, light/dark switching, three
override paths, and migration note for old --chat-* tokens.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…es guide

- Rename chat-messages.mdx → chat-message-list.mdx; update selector and
  class name throughout
- Add chat-popup.mdx, chat-sidebar.mdx, chat-trace.mdx component pages
- Add guides/layout-modes.mdx comparing embedded/popup/sidebar modes
- Update --chat-* token references to --ngaf-chat-* in all existing
  component pages (chat-input, chat-interrupt-panel, chat-subagent-card,
  chat-tool-call-card)
- Drop CHAT_THEME_STYLES/CHAT_MARKDOWN_STYLES from chat.mdx; note
  asymmetric message pattern
- Add new pages and layout-modes to docs-config.ts navigation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The click handler on the pill div violated angular-eslint's
template/click-events-have-key-events and template/interactive-supports-focus
rules. The textarea inside the pill receives focus natively when its visible
area is clicked, so the handler was a redundant convenience.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…0.0.4)

Found via fresh-install smoke test against @ngaf/chat@0.0.3. Multiple
critical UX bugs that shipped to npm:

1. Message content never rendered. chat-message used `<ng-content/>`
   inside `@switch @case` blocks; Angular's content projection is
   resolved at view-creation, so projected text/templates never
   reached the per-role slots. Result: empty user bubbles and empty
   assistant bodies. Fix: single root-level `<ng-content/>` slot,
   role-driven CSS class on the body wrapper. Caret + controls
   visibility now driven by `data-streaming` / `data-current` /
   `data-role` host attributes + CSS, not @switch.

2. Empty state had no default content and didn't hide. The
   `[chatEmptyState]` slot in `<chat>` had no fallback, so
   first-time consumers saw a blank tall area. Even worse, the
   `[hidden]` attribute on the empty container was overridden by
   `display: flex` so the empty state stayed visible after
   messages existed. Fix: provide default fallback content in the
   ng-content slot (How can I help? / Ask anything to get started)
   and add `.chat-empty[hidden] { display: none; }` rule.

3. Input textarea didn't clear on submit. The new chat-input pill
   used a getter/setter proxy (messageTextProxy) for ngModel
   two-way binding, but ngModel doesn't reactively re-read
   getters when the underlying signal changes. Setting
   `messageText.set('')` after submit didn't update the textarea.
   Fix: switch to `[ngModel]="messageText()"` +
   `(ngModelChange)="messageText.set($event)"` — signal-native
   binding that updates reactively.

Fixes validated end-to-end against a fresh `ng new` consumer with
no Tailwind, no postcss, no global stylesheet. Embedded mode
renders user bubble + streaming markdown assistant correctly;
popup mode opens with full conversation; empty state shows with
default content and hides cleanly.

Bumps @ngaf/chat to 0.0.4.

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

vercel Bot commented May 1, 2026

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

Project Deployment Actions Updated (UTC)
cacheplane Ready Ready Preview, Comment May 1, 2026 10:23pm
cacheplane-minting-service Error Error May 1, 2026 10:23pm

Request Review

@blove
Copy link
Copy Markdown
Contributor Author

blove commented May 1, 2026

Superseded by clean branch — the original branch had divergent history with the squashed PR #157 merge. Replacing with claude/chat-04 (cherry-picked the same fixes onto fresh main + adds the marked-required peer change).

@blove blove closed this May 1, 2026
@blove blove deleted the claude/dazzling-dewdney-887eac branch May 7, 2026 16:30
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