Problem
Generative UI components lack smooth progressive rendering. The experience is jarring in two distinct ways:
1. WidgetRenderer (HTML/SVG) flickers during streaming
The WidgetRenderer streams content via postMessage, but every update replaces content.innerHTML wholesale (widget-renderer.tsx, bridge JS line 364). This destroys and recreates the entire DOM on each token, causing:
- Visible flickering as elements are torn down and rebuilt
- CSS animations re-trigger — the
fadeSlideIn stagger animations on #content > * children (lines 305-319) restart on every update since the elements are new
- No visual continuity — elements that were already rendered get replaced with identical copies
Compare this to Claude Artifacts, where SVG/HTML elements appear one by one with staggered fade-in animations. Once an element is on screen it stays stable — new elements are appended, not re-injected.
2. Structured React components render all-at-once
- BarChart / PieChart — entire chart + legend appears in a single frame when data arrives from the agent
- MeetingTimePicker — all time slots appear simultaneously
These components have no concept of streaming or progressive reveal.
Desired Behavior
WidgetRenderer:
- Diff incoming HTML against current DOM instead of replacing innerHTML (or use a morphing library)
- New top-level elements should fade/slide in individually as they stream in
- Already-rendered elements should remain stable (no flicker, no animation restart)
- Reference: Claude Artifacts progressive SVG rendering — elements appear one by one with stagger animation
Structured components (charts, pickers):
- Animate data points / slices / slots appearing progressively
- Or at minimum, use a staggered entrance animation when the component first mounts
Technical Notes
widget-renderer.tsx line 364: content.innerHTML = tmp.innerHTML is the root cause of flickering
FORM_STYLES_CSS lines 305-319 already define fadeSlideIn stagger animations — these would work correctly if elements were appended rather than replaced
- A DOM-morphing approach (e.g.
morphdom, idiomorph, or manual diffing) could preserve existing nodes while patching in new content
- The 800ms debounce settle detection (
htmlSettled) could remain as-is for "streaming complete" signaling
Problem
Generative UI components lack smooth progressive rendering. The experience is jarring in two distinct ways:
1. WidgetRenderer (HTML/SVG) flickers during streaming
The WidgetRenderer streams content via
postMessage, but every update replacescontent.innerHTMLwholesale (widget-renderer.tsx, bridge JS line 364). This destroys and recreates the entire DOM on each token, causing:fadeSlideInstagger animations on#content > *children (lines 305-319) restart on every update since the elements are newCompare this to Claude Artifacts, where SVG/HTML elements appear one by one with staggered fade-in animations. Once an element is on screen it stays stable — new elements are appended, not re-injected.
2. Structured React components render all-at-once
These components have no concept of streaming or progressive reveal.
Desired Behavior
WidgetRenderer:
Structured components (charts, pickers):
Technical Notes
widget-renderer.tsxline 364:content.innerHTML = tmp.innerHTMLis the root cause of flickeringFORM_STYLES_CSSlines 305-319 already definefadeSlideInstagger animations — these would work correctly if elements were appended rather than replacedmorphdom,idiomorph, or manual diffing) could preserve existing nodes while patching in new contenthtmlSettled) could remain as-is for "streaming complete" signaling