Skip to content

feat(cockpit-langgraph): redesign 7 langgraph examples' bespoke UI (encapsulated CSS, sky-blue accent)#777

Merged
blove merged 8 commits into
mainfrom
blove/langgraph-examples-redesign
Jul 7, 2026
Merged

feat(cockpit-langgraph): redesign 7 langgraph examples' bespoke UI (encapsulated CSS, sky-blue accent)#777
blove merged 8 commits into
mainfrom
blove/langgraph-examples-redesign

Conversation

@blove

@blove blove commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Applies the encapsulated-CSS-on---ds-* redesign (proven on the render examples, #759/#761) to the 7 langgraph examples whose bespoke UI was rendering unstyled — the same root cause: Tailwind utilities compile to zero rules in the embedded example builds, so anything not drawn by the pre-styled @threadplane/chat library was unstyled. Accent = sky-blue --ds-accent.

Audited scope (live, all 9 langgraph examples)

Only the affected ones are touched. streaming + deployment-runtime are pure library chat and were confirmed fine — left alone.

Example Bespoke UI redesigned
durable-execution vertical + inline step trackers (status circles/spinners, semantic green/amber/red)
time-travel checkpoint timeline (rows, numbered badges, Replay/Fork)
persistence thread picker (+ inline (mouseenter)/(mouseleave) JS hacks → real :hover)
subgraphs subagent status-dot list
memory learned-facts key/value list
interrupts approval-card body + edit form (inline style= → encapsulated classes)
client-tools weather-card + confirm-booking cards (token remap --tplane-chat-*--ds-*)

Notes

  • Semantic status (complete/running/error) uses local --st-* constants — the design system has no --ds-success/warning/error tokens.
  • Fixed a latent no-op: sidebarWidth="w-64"/"w-56" (Tailwind class names passed to an input that expects a CSS length) → "16rem"/"14rem".
  • Every example's handlers, signals, store/provider wiring, and schema-anchored ViewProps inputs preserved; only styling changed. Library components untouched. interrupts welcome-suggestion text kept byte-identical (e2e-asserted).

Verification

  • ✅ All 7 build within budget (nx run-many -t build); bespoke templates Tailwind-free (grep)
  • Live-agent verification of populated panels + conditional cards (interrupt approval, tool cards) to follow on the production deploy.

Plan: docs/superpowers/plans/2026-07-07-langgraph-examples-redesign.md

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
threadplane Ready Ready Preview, Comment Jul 7, 2026 11:42pm

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 2m 37s —— View job


Code Review

  • Gather context and read PR diff
  • Review component files for correctness, type safety, Angular pitfalls
  • Check tsconfig changes
  • Post findings

Summary

The approach is solid: all 7 components correctly encapsulate styles on --ds-* tokens, every --tplane-chat-* reference and Tailwind utility is removed from bespoke templates, handlers/signals/inputs are preserved, and the sidebarWidth and inline-hover anti-patterns are properly fixed. Three issues found below.


Issues

1. Specificity bug — active row loses accent on hover (time-travel.component.ts)inline comment

.row:hover has specificity (0,2,0) vs .row--active's (0,1,0), so hovering the selected checkpoint row applies --ds-surface-tinted and overwrites the accent-surface background. persistence.component.ts already gets this right with a .thread--active:hover override; time-travel needs the same:

.row--active:hover {
  background: var(--ds-accent-surface, rgba(100, 195, 253, 0.08));
}

2. Missing type="button" on Replay/Fork buttons (time-travel.component.ts)inline comment

Both action buttons lack type="button"; browsers default to type="submit". Not an active bug today (no wrapping <form>), but inconsistent with every other button added in this PR (persistence, interrupts all declare type="button").

3. --st-error defined but unreachable (durable-execution.component.ts, step-pipeline.component.ts)inline comment

Both components declare --st-error: #e0645a in :host, but PipelineStep.status is 'pending' | 'active' | 'complete' with no error branch in either template. Dead code; safe to remove unless an error state is planned (it is used correctly in subgraphs.component.ts).


Looks Good

  • Token remap (--tplane-chat-*--ds-*) is complete across all 7 examples; grep confirms no stragglers.
  • --ds-accent-glow in interrupts.component.ts is a real token (libs/design-tokens/src/lib/tokens.css:15) — no missing-fallback issue.
  • persistence.component.ts correctly handles .thread--active:hover and removes all mouseenter/mouseleave handlers.
  • tsconfig.app.json spec-exclude additions are uniform and correct across all 7 projects.
  • ChangeDetectionStrategy.OnPush and all signal/computed wiring untouched; no new subscriptions or leaks introduced.
  • WELCOME_SUGGESTIONS text in interrupts.component.ts preserved byte-for-byte (e2e-asserted).

@blove blove enabled auto-merge (squash) July 7, 2026 23:39
Comment on lines +76 to +79
.row--active {
background: var(--ds-accent-surface, rgba(100, 195, 253, 0.08));
border-color: var(--ds-accent-border, rgba(100, 195, 253, 0.25));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specificity bug: hovered active row loses accent background

.row:hover has specificity (0,2,0) (one class + one pseudo-class) which beats .row--active's (0,1,0) (one class). When the user hovers the currently-selected checkpoint row, .row:hover wins and the accent-surface background is overwritten by --ds-surface-tinted.

persistence.component.ts already handles this correctly with a .thread--active:hover override. Same fix needed here:

Suggested change
.row--active {
background: var(--ds-accent-surface, rgba(100, 195, 253, 0.08));
border-color: var(--ds-accent-border, rgba(100, 195, 253, 0.25));
}
.row--active {
background: var(--ds-accent-surface, rgba(100, 195, 253, 0.08));
border-color: var(--ds-accent-border, rgba(100, 195, 253, 0.25));
}
.row--active:hover {
background: var(--ds-accent-surface, rgba(100, 195, 253, 0.08));
}

Comment on lines 173 to 177
<button
class="px-2 py-1 text-xs rounded bg-[var(--tplane-chat-surface-alt)] text-[var(--tplane-chat-text)] hover:bg-[var(--tplane-chat-surface-alt)] transition-colors"
class="btn"
title="Replay from this checkpoint"
(click)="replay(state, i)"
>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing type="button" on both Replay and Fork buttons. Without an explicit type, browsers default to type="submit". These buttons are not inside a <form> element so it doesn't fire a submission today, but it's fragile — if the template ever gains a wrapping form these will submit it unintentionally. All other new buttons in this PR (persistence, interrupts) correctly declare type="button".

Suggested change
<button
class="px-2 py-1 text-xs rounded bg-[var(--tplane-chat-surface-alt)] text-[var(--tplane-chat-text)] hover:bg-[var(--tplane-chat-surface-alt)] transition-colors"
class="btn"
title="Replay from this checkpoint"
(click)="replay(state, i)"
>
<button
type="button"
class="btn"
(click)="replay(state, i)"
>

Comment on lines +41 to +47
:host {
--st-done: #2ea567;
--st-active: #e0a850;
--st-error: #e0645a;
}
.panel {
padding: 1rem;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--st-error is defined here (and in step-pipeline.component.ts) but is never consumed — PipelineStep.status is 'pending' | 'active' | 'complete' with no error state, and neither template has an error branch. The variable is harmless dead code, but it's misleading (it implies an error state that doesn't exist in the durable-execution graph). Safe to remove from both files unless an error status is planned.

@blove blove merged commit 198bf70 into main Jul 7, 2026
31 checks passed
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