Fix squashed Mermaid diagrams in markdown preview (#61260)

## Summary

Wide Mermaid diagrams in Markdown Preview were forced through
`max_w_full()`, so both width and height shrank to the pane and text
became unreadable/blurry. There was no horizontal pan.

Markdown Preview already sets `code_block_overflow_x_scroll: true` for
fenced code blocks. Mermaid ignored that flag.

This change gates layout on that style flag:

- **Preview** (`code_block_overflow_x_scroll`): keep the raster at
intrinsic size and enable `overflow_x_scroll` (with
`restrict_scroll_to_axis`) so wide diagrams stay readable and can be
panned horizontally.
- **Compact UIs** (e.g. agent): keep previous `max_w_full()` fit-to-pane
behavior.

Fixes #61051

## Test plan

- [ ] Open a markdown file with a wide ` ```mermaid ` flowchart (e.g.
multi-column TB graph) in Markdown Preview
- [ ] Confirm diagram is not crushed to pane width; text remains legible
at default scale
- [ ] Confirm horizontal scroll/pan works on the diagram without
stealing vertical page scroll
- [ ] Confirm compact surfaces that leave `code_block_overflow_x_scroll`
off still fit diagrams to width
- [ ] Confirm mermaid scale fence info still works (` ```mermaid 150 `)
- [ ] Confirm Preview/Code tabs and copy button still work

---

Release Notes:

- Fixed wide Mermaid diagrams in Markdown Preview being squashed and
illegible
This commit is contained in:
Atharva Ajmera authored and GitHub committed 2026-07-24 00:39:01 +00:00
1 parent e12992cae3
commit fd8f0cdfd7
1 file changed
+32 -20
+32 -20
View File
@@ -322,6 +322,8 @@ pub(crate) fn render_mermaid_diagram(
let cached = mermaid_state.cache.get(&parsed.contents);
let render_result = cached.and_then(|cached| cached.render_image.get());
let show_interactive = copy_button_visibility != CopyButtonVisibility::Hidden;
// Preview keeps diagrams at natural size + scroll instead of crushing them via max_w_full (#61051).
let allow_overflow_x = style.code_block_overflow_x_scroll;
let code = parsed.contents.contents.clone();
@@ -333,16 +335,7 @@ pub(crate) fn render_mermaid_diagram(
let body = if showing_code {
render_mermaid_code_view(&parsed.contents.contents)
} else {
div()
.w_full()
.child(
img(ImageSource::Render(render_image.clone()))
.max_w_full()
.with_fallback(|| {
Label::new("Failed to Load Mermaid Diagram").into_any_element()
}),
)
.into_any_element()
render_mermaid_image(render_image.clone(), allow_overflow_x, source_offset)
};
container
@@ -382,16 +375,11 @@ pub(crate) fn render_mermaid_diagram(
container
.child(
div()
.w_full()
.child(
img(ImageSource::Render(fallback.clone()))
.max_w_full()
.with_fallback(|| {
div()
.child(Label::new("Failed to load mermaid diagram"))
.into_any_element()
}),
)
.child(render_mermaid_image(
fallback.clone(),
allow_overflow_x,
source_offset,
))
.with_animation(
"mermaid-fallback-pulse",
Animation::new(Duration::from_secs(2))
@@ -439,6 +427,30 @@ pub(crate) fn render_mermaid_diagram(
}
}
/// Renders a mermaid diagram image, scrolling at intrinsic size in preview or fit-to-pane elsewhere.
fn render_mermaid_image(
render_image: Arc<RenderImage>,
allow_overflow_x: bool,
source_offset: usize,
) -> AnyElement {
let image = img(ImageSource::Render(render_image))
.with_fallback(|| Label::new("Failed to Load Mermaid Diagram").into_any_element());
if allow_overflow_x {
div()
.id(("mermaid-scroll", source_offset))
.w_full()
.map(|mut container| {
container.style().restrict_scroll_to_axis = Some(true);
container.overflow_x_scroll()
})
.child(image)
.into_any_element()
} else {
div().w_full().child(image.max_w_full()).into_any_element()
}
}
fn render_mermaid_tab_header(
source_offset: usize,
showing_code: bool,