Skip to content

fix(chat): scope tool-call rendering per-message + style genui demo views#446

Merged
blove merged 5 commits into
mainfrom
claude/genui-visual-polish
May 18, 2026
Merged

fix(chat): scope tool-call rendering per-message + style genui demo views#446
blove merged 5 commits into
mainfrom
claude/genui-visual-polish

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 18, 2026

Summary

Three fixes uncovered while testing the c-generative-ui demo locally with chrome MCP:

1. Duplicate tool-call cards in every AI bubble

<chat-tool-calls> was rendering the agent's GLOBAL tool-call list whenever the AI message's content was a plain string — which the LangGraph adapter always produces (its extractTextContent reduces complex content to a string). Every AI message in a thread re-rendered every tool call; a 3-AI-message thread with 4 tool calls showed three identical blocks of 4 cards (verified via chrome MCP DOM query).

Fix: add Message.toolCallIds?: string[] populated by the LangGraph adapter from raw tool_calls[].id. chat-tool-calls prefers this per-message list; the legacy Anthropic-style content-block path stays as a fallback; the global-list fallback now fires only when no message is provided at all. Verified post-fix: 3 mounted <chat-tool-calls> elements but only 1 non-empty, exactly matching the one AI message that emitted tool calls.

2. Stat cards / charts / table rendered as bare text

cockpit-chat-generative-ui-angular doesn't have Tailwind configured — styles.css only imports @ngaf/example-layouts/theme.css. All Tailwind classes (rounded-lg, border-white/10, bg-white/5, flex, gap-6, text-emerald-400, etc.) were silently no-ops, so:

  • Stat cards rendered as plain stacked text (label / value / delta)
  • Bar + line charts had no card chrome, no titles' styling
  • Data table had no header row styling, no zebra striping
  • Container layout fell back to default block flow

Fix: convert all 6 view components to scoped Angular styles with raw CSS:

  • stat-card: card chrome, uppercase label, large numeric value, colored delta via [data-trend] attribute (green up / red down)
  • bar-chart + line-chart: card chrome, gradient SVG fills, gridlines, consistent title + axis-label styling; line chart adds an area-fill path under the line
  • data-grid: card chrome, uppercase header row, zebra striping, tabular-nums, horizontal scroll
  • dashboard-grid: vertical flex stack with consistent gap
  • container: CSS grid that distributes children evenly in row direction, collapses to 2-col then 1-col at responsive breakpoints

3. Specs updated

stat-card, container, dashboard-grid specs asserted on the old Tailwind class names. Updated to assert on the new attribute-based markers (data-trend="up", data-direction="row", div.dashboard-grid).

Files

  • libs/chat/src/lib/agent/message.ts — add toolCallIds?: string[]
  • libs/chat/src/lib/primitives/chat-tool-calls/chat-tool-calls.component.ts — prefer per-message toolCallIds
  • libs/langgraph/src/lib/agent.fn.ts — populate toolCallIds in toMessage
  • cockpit/chat/generative-ui/angular/src/app/views/*.component.ts — 6 components rewritten with scoped CSS
  • cockpit/chat/generative-ui/angular/src/app/views/*.component.spec.ts — 3 specs updated

Test plan

  • pnpm nx run cockpit-chat-generative-ui-angular:test — green (21 tests pass after spec updates)
  • pnpm nx run chat:test — green
  • pnpm nx run langgraph:test — green
  • All affected builds green
  • Chrome MCP smoke against local dev: dashboard renders with proper card chrome, ONE block of tool-call cards (not three), stat-card deltas color-coded (green/red), charts have card backgrounds + axis labels + area fills, table has zebra striping
  • CI

🤖 Generated with Claude Code

blove and others added 3 commits May 18, 2026 15:35
chat-tool-calls.toolCalls fell back to the agent's GLOBAL toolCalls
list whenever the message had string content — which is the LangGraph
adapter's default (extractTextContent always reduces complex content
to a string). Every AI bubble in a thread re-rendered the entire
thread's tool calls; with 3 AI messages and 4 tool calls, the chat
showed 3 identical tool-call blocks.

Fix: add `Message.toolCallIds?: string[]` populated by the LangGraph
adapter from raw `tool_calls[].id`. chat-tool-calls prefers this
per-message list when present; the legacy Anthropic-style content-block
path stays as a fallback; the global-list fallback now fires ONLY when
no message context is provided at all.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The cockpit-chat-generative-ui-angular app doesn't have Tailwind
configured — styles.css only imports theme tokens. All Tailwind
classes (rounded-lg, border-white/10, bg-white/5, flex, gap-6, etc.)
were silently no-ops, rendering stat cards as bare stacked text and
charts/tables without their card chrome.

Convert all 6 view components to scoped Angular styles (or styleUrls)
using raw CSS:

- stat-card: card chrome, uppercase tracked label, large value,
  colored delta (green for up, red for down via data-trend attr)
- bar-chart + line-chart: card chrome, gradient fills, gridlines,
  consistent axis-label and title styling
- line-chart: area-fill path under the line via SVG path d=
- data-grid: card chrome, uppercase header row, zebra striping,
  tabular-nums, horizontal scroll for narrow widths
- dashboard-grid: vertical flex stack, 16px gap
- container: CSS grid with row direction = equal columns based on
  child count, collapses to 2-col then 1-col at responsive breakpoints

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

vercel Bot commented May 18, 2026

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

Project Deployment Actions Updated (UTC)
threadplane Ready Ready Preview, Comment May 18, 2026 10:57pm

Request Review

PR #444 dropped visible label text from the demo shell toolbar to tighten
the layout, but the examples/chat e2e helpers used `.filter({ hasText:
label })` to find the four toolbar fields (Model, Effort, Gen UI, Theme)
— with labels gone, ~5 tests failed on every CI run since #444 merged.

Add `data-field` attributes to the four `.demo-shell__field` wrappers
and switch the e2e helpers + the one inlined locator in
model-picker.spec.ts to query by attribute. Helper signatures unchanged
(label arg now maps to data-field via a small lookup table) so call
sites in control-palette, color-scheme, model-picker, etc. need no
changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@blove blove merged commit f9fde32 into main May 18, 2026
17 of 18 checks passed
@blove blove deleted the claude/genui-visual-polish branch May 18, 2026 23:04
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