fix(chat,langgraph): jank — stable id + global keyframes + round send + host overflow#175
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The 0.0.9 jank fix switched chat-message-list to `track message.id`, but the optimistic human message injected at submit() had no id — so toMessage() called randomId() on every BaseMessage→Message recompute. Each token re-emission produced a fresh id for the user bubble, defeating track-by-id and tearing down the chat-message DOM (and its caret / typing-dot animations) on every streamed token. - stream-manager.bridge: stamp optimistic input messages with an `optimistic-<ts>-<rand>` id at injection time. Real LangGraph echoes with a server id arrive as a separate merge, naturally taking over. - agent.fn: WeakMap-cache projected Message objects by raw BaseMessage identity so the projected `id` is stable across recomputes when the raw reference is stable (additional belt-and-braces for caret/typing animation continuity). - chat.component: only mark the LAST assistant message as `streaming=true` (was every assistant). Avoids re-painting historical messages' caret/streaming attrs every token. - Bumps: @ngaf/chat 0.0.9 → 0.0.10, @ngaf/langgraph 0.0.3 → 0.0.4. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three additional jank fixes for 0.0.10: 1. Hoist @Keyframes (typing-dot, caret-blink, spin, pulse) into the global ROOT_TOKEN_STYLES sheet that's already auto-injected into <head>. Previously they lived in CHAT_HOST_TOKENS and were appended to every chat component's styles array. Angular's emulated view encapsulation scopes @Keyframes names per-component, which can desynchronise from `animation: name` references when those live in a sibling style helper string. Result: the typing dots rendered but never animated. Hoisting to global scope makes the names match what component CSS references (Angular leaves `animation:` props untouched). 2. Make the send button fully round (`border-radius: 9999px`) instead of the 8px button radius — matches the floating-launcher aesthetic. 3. Constrain the chat host with `overflow: hidden` and add `flex: 1 1 auto; max-height: 100%` so content can never push the embedding page into a scroll state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1e46bc8 to
a251674
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
After 0.0.9 the user reported residual jank: caret animation flicker, typing dots showing but not animating, page-level scroll on embedded mode, and an angular send button. Investigation in this PR addresses each.
Changes
stream-manager.bridge): stamp injected human messages with an `optimistic--` id. Without this, `toMessage()` called `randomId()` on every recompute → fresh `message.id` per token → `track message.id` tore down the user bubble repeatedly.Versions
Test plan
🤖 Generated with Claude Code