Skip to content

fix: add horizontal scroll to rendered markdown code blocks#10008

Open
yingxuel wants to merge 3 commits intowarpdotdev:masterfrom
yingxuel:fix/rendered-markdown-horizontal-scroll
Open

fix: add horizontal scroll to rendered markdown code blocks#10008
yingxuel wants to merge 3 commits intowarpdotdev:masterfrom
yingxuel:fix/rendered-markdown-horizontal-scroll

Conversation

@yingxuel
Copy link
Copy Markdown

@yingxuel yingxuel commented May 4, 2026

Description

Rendered markdown code blocks in the notebook file view were silently clipped at the pane edge with no affordance to reach overflowing content. Switching to Raw mode showed a horizontal scrollbar; Rendered mode had none.

Root cause: RenderableRunnableCommand drew paragraphs directly to the scene with no clip layer and no scroll state. Monospace code lines wider than the container extended past the right edge and were swallowed by the outer editor clip. (RenderableTable already has a full horizontal-scroll implementation; this brings code blocks to parity.)

Changes:

  • crates/editor/src/render/element/paint.rs — adds draw_paragraph_scrolled, which temporarily increments RenderContext::nested_horizontal_scroll so that content_to_screen shifts text, selection highlights, cursors, and syntax-highlight decorations together under the scroll offset.
  • crates/editor/src/render/element/runnable_command.rs — tracks scroll_left, natural_width, viewport_bounds, scrollbar, scrollbar_hovered, and scrollbar_drag; wraps code content in a BoundedByActiveLayerAnd clip layer; renders a horizontal scrollbar thumb (reusing the table scrollbar colours from the active theme); handles shift-scroll / horizontal trackpad and scrollbar drag in dispatch_event, mirroring RenderableTable.
  • 10 unit tests covering: max-scroll arithmetic (fits / exact / overflow), ScrollData construction, delta gating (plain vertical → None, shift-scroll and horizontal trackpad → Some), line-multiplier scaling for imprecise scroll, and scroll_left clamping at both edges.

Linked Issue

Fixes #9089

  • The linked issue is labeled ready-to-spec or ready-to-implement.
  • Where appropriate, screenshots or a short video of the implementation are included below (especially for user-visible or UI changes).

Screenshots / Videos

recording_9089.mov

Testing

  • Added 10 unit tests in runnable_command.rs (see code_block_scroll_tests module); all pass with cargo nextest run -p warp_editor.
  • Full warp_editor suite: 422/422 pass, zero regressions.
  • Note on presubmit: 6 tests were already failing on master before this branch was created (verified by checking out master without these changes). These failures are pre-existing and unrelated to this PR.

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-BUG-FIX: Rendered markdown code blocks now scroll horizontally when content overflows the pane width, matching Raw mode behaviour.

…ev#9089)

Code blocks in the rendered-markdown notebook view were silently clipped
at the pane edge with no way to reach overflowing content. Raw mode
already had a horizontal scrollbar; this brings rendered mode to parity.

Root cause: `RenderableRunnableCommand` drew paragraphs with no clip
layer and no scroll state, so text wider than the container was painted
off-screen and swallowed by the outer editor clip.

Changes:
- `paint.rs`: add `draw_paragraph_scrolled` which temporarily increments
  `RenderContext::nested_horizontal_scroll` so that `content_to_screen`
  shifts text, selection, cursors, and decorations together.
- `runnable_command.rs`: track `scroll_left`, `natural_width`,
  `viewport_bounds`, `scrollbar`, `scrollbar_hovered`, and
  `scrollbar_drag`; paint a `BoundedByActiveLayerAnd` clip layer around
  code content; render a horizontal scrollbar thumb (same colours as the
  table scrollbar); handle shift-scroll / horizontal trackpad gesture and
  scrollbar drag in `dispatch_event` — mirroring `RenderableTable`.
- 10 unit tests covering max-scroll arithmetic, scroll data, delta
  gating (vertical vs shift/horizontal vs precise), line-multiplier
  scaling, and scroll-left clamping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cla-bot cla-bot Bot added the cla-signed label May 4, 2026
@github-actions github-actions Bot added the external-contributor Indicates that a PR has been opened by someone outside the Warp team. label May 4, 2026
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 4, 2026

@yingxuel

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds nested horizontal scrolling and scrollbar handling for rendered markdown runnable code blocks.

Concerns

  • The new scroll offset only affects painting/event dispatch inside RenderableRunnableCommand; model-level hit testing for code blocks still uses unscrolled coordinates, so clicks, selection, cursor placement, and link hover can target the wrong text after horizontal scrolling.

Verdict

Found: 0 critical, 1 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread crates/editor/src/render/element/runnable_command.rs Outdated
…esting

Moves `scroll_left` from the `RenderableRunnableCommand` struct into
`BlockItem::RunnableCodeBlock` (as `Cell<Pixels>`, matching the table
pattern) so that hit-testing code paths — `character_bounds` and
`coordinate_to_location` — can account for horizontal scroll when
resolving clicks, selections, and link hovers inside scrolled code blocks.
Also strengthens types from `f32` to `Pixels` throughout, and moves scroll
clamping from `paint()` to `layout()` so it runs before the scene is built.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@yingxuel
Copy link
Copy Markdown
Author

yingxuel commented May 4, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 4, 2026

@yingxuel

I'm re-reviewing this pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This adds per-code-block horizontal scroll state, clipping, scrollbar painting, and adjusted hit-testing for rendered markdown code fences.

Concerns

  • The new code-block clip layer is not marked click-through, unlike the table implementation it mirrors. That can make the layer cover the rich-text content for pointer hit-testing and break selecting/clicking inside code blocks.

Verdict

Found: 0 critical, 1 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread crates/editor/src/render/element/runnable_command.rs
Co-authored-by: oz-for-oss[bot] <277970191+oz-for-oss[bot]@users.noreply.github.com>
@yingxuel
Copy link
Copy Markdown
Author

yingxuel commented May 4, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 4, 2026

@yingxuel

I'm re-reviewing this pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds horizontal overflow clipping, scroll state, scrollbar rendering, event handling, and hit-testing updates for rendered markdown code blocks.

Concerns

  • Scrollbar drag interaction state is stored on the renderable block, which is rebuilt during layout after notifications, so the thumb drag can be lost immediately after mouse down.

Verdict

Found: 0 critical, 1 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

if thumb_hit {
let scroll_data =
code_block_scroll_data(natural_width, container_width, scroll_left.get());
self.scrollbar_drag = Some(CodeBlockScrollDrag {
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.

⚠️ [IMPORTANT] ctx.notify() can trigger a layout pass, and RichTextElement::layout rebuilds RenderableBlocks, so storing the drag state on RenderableRunnableCommand drops it before the next LeftMouseDragged; persist this interaction state in the render model like LaidOutTable does.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed external-contributor Indicates that a PR has been opened by someone outside the Warp team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rendered Markdown Lacks Horizontal Scroll

1 participant