Skip to content

fix: preserve streaming animations across text and code - #619

Open
rogersnm wants to merge 4 commits into
vercel:mainfrom
rogersnm:fix/preserve-in-flight-word-animation
Open

fix: preserve streaming animations across text and code#619
rogersnm wants to merge 4 commits into
vercel:mainfrom
rogersnm:fix/preserve-in-flight-word-animation

Conversation

@rogersnm

@rogersnm rogersnm commented Sep 12, 2026

Copy link
Copy Markdown

Description

Streaming updates can truncate active fades, completion can reveal pending text instantly, replay can skip opening animations, generated list whitespace can make new words appear already displayed, and code blocks can appear ahead of the text before them. Preserve animation history and use the shared animation timeline for text and code.

Type of Change

  • Bug fix

Changes Made

  • Preserve each pending or active fade's original timing across updates, including list markers, checkboxes, images and rules.
  • Let finite Streamdown CSS animations finish after streaming stops, then remove animation attributes/wrappers. Cleanup uses Animation.finished, handles cancellation, and is invalidated when streaming resumes or the final content changes.
  • Discard removed blocks' history and reset the timeline when content is cleared, so replay animates its opening words.
  • Exclude positionless parser-generated layout whitespace from both animation counting passes. Source whitespace still counts; loose-list and tight-to-loose transitions preserve offsets.
  • Animate fenced code as one unit on the shared timeline. Its entry fade follows preceding words without inserting spans into syntax-highlighted content. A stable wrapper preserves the fade while code and highlighting update and while final animations drain. All blocks share one render-pass clock, so parsing time cannot let a later block overtake earlier text.

Animation defaults and the public API are unchanged. Code uses the configured duration and timeline; it does not get per-token syntax animations. Existing callbacks retain their streaming-state semantics.

Testing

  • Streamdown: 1,206 passing tests, including plugin-level code scheduling and a React regression for the persistent code wrapper.
  • pnpm check passes.
  • The patched 2.6.0 distribution builds successfully and passes 111 consumer Markdown/message-bubble tests.
  • 14 consumer browser checks pass across Chromium and WebKit: pending/active fades, completion/replay, list offsets, asynchronous plugin updates, and code entry ordering, growth and completion. The browser fixture uses real CSS animations and the actual installed component.
  • Full-response playback also verified in both engines, with cold and cached maths loading.

The existing package/website build and six-package test validation from the earlier commits remains described in the linked history. The optional apps/test production build requires an AI Gateway credential; it was not used as a gate.

Screenshots/Demos

Original before/after animation recording · Quarter-speed recording

The original recording covers the update/completion/replay fixes; it predates the list-offset and code-entry additions. Its 50 ms updates, 250 ms fades and 10 ms stagger are comparison settings, not changed defaults.

List reproduction: render 1. First\n\n2. *But in ourselves, that we, then append are underlings.. Previously “are” could receive a zero-duration fade while adjacent words remained mid-animation.

Code reproduction: deliver a heading and fenced code in the same update with staggered animation enabled. Previously the code bypassed the timeline; now its wrapper receives one slot after the heading and keeps the same fade when the fence grows.

The consumer's separate fix for changing its React key when its maths plugin loads is application-side and is not included here.

Checklist

  • Followed project code style.
  • Added and updated regression tests.
  • Updated the patch changeset.

@vercel

vercel Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

@rogersnm is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@rogersnm rogersnm changed the title fix: preserve text animations through updates, completion, and replay fix: preserve streamed text fades and correct list animation offsets Sep 12, 2026
@rogersnm rogersnm changed the title fix: preserve streamed text fades and correct list animation offsets fix: preserve streaming animations across text and code Sep 12, 2026
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