Fix V2 diagram sizing, scrolling and render failures - #1393
Merged
Paul Lizer (paullizer) merged 2 commits intoSep 3, 2026
Conversation
Diagrams in the V2 chat rendered at roughly a quarter of their natural size, made long threads unusable, and sometimes failed to render with nothing to explain why. Each cause was reproduced against the vendored mermaid 11.17.2 bundle in Chromium before anything was changed. Sizing. The assistant bubble is shrink-to-fit and mermaid emits width="100%", which contributes nothing to intrinsic sizing, so the bubble collapsed to the width of the diagram's own toolbar. Opening the Colors menu introduced a palette row that does have a natural width, which is why the same diagram suddenly became legible. The panel now takes its width from the diagram's measured natural width: 300px to 966px on the reported diagram, and the colour menu no longer resizes anything. Long diagrams. A flowchart at mermaid's 500-edge limit measures 50,466px tall and went straight into the scroll container. The stage is now capped and scrolls internally. MessageBubble was also unmemoised, so every streaming token re-ran the markdown pipeline for every message, and the auto-scroll never re-fired after a diagram rendered asynchronously and grew the thread, which is why the bottom became unreachable. Render failures. The error object was discarded entirely. It is now kept, logged and shown behind a details disclosure, with a render timeout and a source-size guard matching the classic client. Fourteen reproduced parse failures are repaired and retried; the repair runs only after mermaid has already refused the source and is scoped to flowcharts, so nothing that renders today can be changed by it. Viewing. Zoom, a keyboard-operable resize handle whose height is stored on the message beside the colours, and a full-screen viewer. The viewer lives inside MermaidDiagram.tsx so diagram markup still reaches the DOM in exactly one reviewed sanitizer boundary. No new npm package and no remote asset, so the Content-Security-Policy is unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The base branch added an export-registration hook to MermaidDiagram.tsx and moved the version to 0.261.036. Both merged cleanly against the diagram viewer rewrite: `registerExportDiagram` still runs before the early returns, and it still reads the inline SVG through the figure ref, because the new full-screen viewer renders outside the figure rather than inside it. Resolved by hand: - config.py, renumbered to 0.261.037. - release_notes.md, with the diagram viewer entries moved to their new version and the base's 0.261.034 through 0.261.036 sections left in place. Version references in the new test and fix documentation renumbered to match. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
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.
Diagrams in the V2 chat rendered at roughly a quarter of their natural size, made long threads unusable, and sometimes failed to render with nothing to explain why.
Every cause was reproduced against the vendored mermaid 11.17.2 bundle in Chromium, configured exactly as
MermaidDiagram.tsxconfigures it, before anything was changed.Diagrams rendered too small, and grew when Colors was opened
Same bug, seen from two sides. The assistant bubble is a shrink-to-fit flex item, and mermaid emits
width="100%"with a viewBox and no height, which contributes nothing to CSS intrinsic sizing. The bubble therefore collapsed to the width of the diagram's own toolbar. Opening Colors rendered a wrapping palette row that does have a natural width, which is why the same diagram suddenly became legible.Measured in Chromium, using the natural size of the Azure governance diagram from the report:
The panel now takes its width from the diagram's measured natural width. Because that width is definite, the colour menu can no longer resize anything.
flowchart.wrappingWidthis also raised from mermaid's default of 200, which was wrapping long labels into narrow columns and making diagrams taller: the same diagram measures 273 × 955 at 200 and 497 × 867 at 500.Long diagrams broke scrolling
Three compounding faults:
MessageBubblewas not memoised, andreadMaskState()ran unmemoised. The list re-renders on every streaming token and every time the scroll crossed the pinned-to-bottom threshold, so the whole remark/rehype pipeline re-ran for every message in the thread each time.ResizeObservernow follows content that grows late.Some diagrams never rendered, with no diagnostic
The error object was discarded outright —
.catch(() => setState({ status: 'error' })). No message, noconsole.warn, nothing beyond the words "Diagram could not be rendered". There was also no render timeout and no source-size guard, both of which the classic client has.Fourteen distinct parse failures were reproduced, all of them things models actually write:
end,graph,class,styleas node idsEndclosing a subgraphendis acceptedsubgraphwith noenda[""]a[App (main)]a -->|metadata: {}| ba["He said "hello" loudly"]a["A"] b["B"]on one lineb -->with no targetThe reason is now kept, logged, and shown behind Show details, with a Copy source button. Mermaid's limit errors are reworded. Before the reader sees any of that, the source is repaired and rendered once more.
Two properties of the repair matter:
subgraph,end, square labels and piped edge labels all mean something else in the other diagram types —||--o{in anerDiagram, for one.No way to make a diagram bigger
−/+/ fit, scaling between 0.4× and 4× of the fit-to-width scale.ImageLightboxestablished.The viewer is defined inside
MermaidDiagram.tsxrather than its own file. It writes diagram markup to the DOM, andtest_v2_rich_rendering.py::test_sanitizer_boundary_at_every_html_sinkfixes the set of components allowed to do that; keeping it in the reviewed file preserves that invariant rather than widening it.Prompt guidance
The guidance now names the reserved words, requires a lowercase
endfor everysubgraph, tells the model not to carry placeholders such as<random GUID>out of pasted text into a label, and asks for short labels across several nodes instead of one node holding a dozen<br/>lines.Defects caught in review
Four, all silent rather than visible, each fixed with a regression test:
source_hash, then re-stamped with the new fingerprint — defeating the guard the client already honours.endis both the most common reserved node id and the keyword closing asubgraph. Renaming every occurrence rewrote the terminators, so one was appended at the bottom and everything after the original was swallowed into the group. The result still parsed, so it showed the wrong structure rather than an error.{"height": Infinity}returned a 500.json.loadsaccepts the bareInfinitytoken andround(float('inf'))raisesOverflowError, which is not aVisualStyleError.Validation
functional_tests/test_v2_diagram_viewer_controls.py— 18 checks, including 58 bundled TypeScript behaviour checks.Verified in Chromium against the real mermaid bundle: all 14 reproduced failures render after repair; all 6 working diagrams are untouched; the layout measurements above; and
DiagramStagemounted directly to measure fit scale, zoom, resize, clamping and reset.Full suite re-run and passing after merging the base branch: diagram viewer 18, visual style 16, rich rendering 13, inline diagram 5, prompt guidance 7, mermaid server render 13, browser rasterizer 3, export mermaid/tex 18, agent-model exclusivity 9, reasoning persistence 7, export progress 8, docs coverage 7, docs quality 6. Typecheck and
vite buildclean.Notes
No new npm package and no remote asset. Mermaid and DOMPurify were already vendored locally, so the
default-src 'self'Content-Security-Policy is unchanged.Version
0.261.036→0.261.037.