Skip to content

feat(narratives): render interleaved text and chart blocks in the UI - #577

Merged
nick-nlb merged 4 commits into
datacommonsorg:mainfrom
nick-nlb:narratives-agent-loop-d3-ui-blocks
Oct 31, 2026
Merged

nick-nlb merged 4 commits into
datacommonsorg:mainfrom
nick-nlb:narratives-agent-loop-d3-ui-blocks

Conversation

@nick-nlb

Copy link
Copy Markdown
Collaborator

Overview

#576 switched the server's SSE content frame payload from {text} and {chart_config} to {block}. This PR updates the React UI to accumulate those blocks and render text and charts interleaved in the order they were emitted.

  1. Block streaming: The chat hook collects {block} frames in order and joins text blocks with a blank line, so the answer text matches the server's signed transcript.
  2. Interleaved rendering without layout shifts: As before #576, the skeleton stays up until the turn's terminal event arrives and the answer then reveals word by word in reading order. Charts sit between the paragraphs they belong to; the answer is laid out behind the skeleton until every chart has drawn or reported no data, for at most 2 seconds, so a chart that settles in that time moves nothing once the answer is shown. A chart that is still loading after 2 seconds can change height after the answer appears.
  3. Chart options: Chart tiles pass the resolved per-capita, facet, ranking, and sort options to the Data Commons web components.
  4. Multi-source citations: [N, M] markers render as separate citation chips in prose and in Markdown tables.

The core files to review are ui/src/hooks/use_sse_chat.ts, ui/src/components/panel_answer.tsx, and ui/src/components/tile_chart.tsx.

Related Issues

This is the seventeenth step in the continued agent loop update sequence, following #547, #549, #550, #558, #559, #562, #563, #564, #565, #566, #568, #569, #570, #571, #572, #574, and #576.

Changes Made

  • Citation markers: Adds a shared parser for single ([1]) and multi-source ([1, 2]) citation markers, used by both prose citation chips and Markdown tables.
  • Changes to previously merged code: The chat hook reads {block} frames instead of {text} and {chart_config} and drops malformed blocks; a turn with charts but no answer text shows only its error, as before #576. The answer panel renders blocks in emission order and keeps the existing word-by-word reveal, now spread across text blocks; the rendering path for {text} and {chart_config} turns is removed because nothing produces those turns anymore. The chart tile maps the new chart options onto the web components and reports when its charts have drawn, the chart settle poll reports when it stops watching a chart, the turn view holds the answer invisibly behind the skeleton until its charts settle, the Markdown card drops its unused streaming badge, the word-reveal plugin accepts a start offset, and the debug provenance inspector reads charts from blocks.
  • Unit tests: Cover block accumulation and malformed blocks, block order, waiting for charts before the reveal (including the time cap), the reading-order reveal across blocks, chart attributes and tags for each chart kind, and multi-source citations.

Testing Done

  • pnpm test:ui (vitest run): 32 files, 349 passed (28 files, 304 passed on main).
  • pnpm lint:ui (tsc --noEmit and biome check): passed across 58 checked files (53 on main).
  • pnpm test:agent (uv run pytest): 1,706 passed.
  • pnpm lint:agent (ruff format --check . ../deploy, ruff check . ../deploy, and mypy --strict): passed across all 124 source files.
  • pnpm build: passed.
  • pnpm run lint:shell, pnpm run lint:docker, and terraform fmt -check -recursive deploy/terraform-custom-datacommons/: passed (terraform validate fails locally with a pre-existing backend configuration error on main; no deploy/ files were modified).
  • Confirmed that 43 planted bugs across the chat hook, chart tile, citation parsing, answer panel, reveal timing, and provenance inspector each fail pnpm test:ui.

Checklist:

  • Unit tests passed
  • Integration tests passed (N/A: the application has no integration suite)
  • Manual verification
  • Any updated goldens or fixtures were reviewed and are intentional (N/A: no goldens or fixtures changed)

Manual

Ran the server's synthesis, block splitting, and turn signing on a stubbed turn and fed the resulting SSE bytes through the UI's stream parser and components, rendered in a DOM test environment:

  • Confirmed the signed transcript built from the streamed blocks verifies on the next turn.
  • Confirmed the skeleton stays up while blocks stream in, the answer is laid out invisibly behind it once the turn finishes, and it then reveals word by word across all text blocks in reading order, with prose, a Markdown table, and ranking and scatter charts in emission order and the expected web component attributes.
  • Confirmed [1, 2] markers render as two citation chips in prose and move onto table column headers.

Risk & Rollback

There are no live instances of this application yet. This PR completes the SSE {block} contract migration started in #576: until it merges, main streams {block} frames that the UI does not render. Rollback is reverting this PR together with #576.

Follow-ups

  • A subsequent test PR adds golden fixture cases for the distribution, composition, derived, and relation analytics scripts.

Checklist

  • I have read AGENTS.md and followed CODING_GUIDELINES.md, plus FRONTEND.md for UI changes.
  • I have run the app's lint, test, and build commands, as documented in that application's guide.
  • I have commented my code, particularly in hard-to-understand areas.
  • My changes generate no new warnings.

Note: Only Maintainers can approve and merge PRs. Expected initial review time: 3 business days.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request refactors the Narratives UI to support streaming and rendering answers as structured blocks (text and charts) rather than raw text chunks. It introduces a coordinated text reveal mechanism across sequential blocks, waits for charts to settle before displaying the answer, and adds support for composite citation markers (e.g., [1, 2]). Feedback on these changes includes a warning to replace relative parent imports with project path aliases in panel_answer.tsx to align with the repository style guide, and a suggestion to wrap the text reveal schedule calculation in useMemo to prevent unnecessary recalculations on render.

@nick-nlb
nick-nlb marked this pull request as ready for review October 31, 2026 01:50

@juliawu juliawu 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.

Overall looks good! Leaving some gemini comments below.

Comment thread narratives/ui/src/hooks/use_sse_chat.ts Resolved
@nick-nlb
nick-nlb merged commit 2531897 into datacommonsorg:main Oct 31, 2026
12 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.

2 participants