Skip to content

fix: center active search match in CodeMirror viewport#7918

Open
DevRajah wants to merge 1 commit intousebruno:mainfrom
DevRajah:fix-json-search-result-position
Open

fix: center active search match in CodeMirror viewport#7918
DevRajah wants to merge 1 commit intousebruno:mainfrom
DevRajah:fix-json-search-result-position

Conversation

@DevRajah
Copy link
Copy Markdown

@DevRajah DevRajah commented May 5, 2026

Description

This PR improves the positioning of search results in the JSON response view.

Previously, when navigating search matches, the highlighted result was often positioned near the bottom of the viewport. This made it difficult to view surrounding JSON context and required additional manual scrolling.

What changed

  • The active search match is now positioned closer to the center of the editor viewport
  • This provides better visibility of surrounding JSON content (above and below the match)
  • Improves navigation experience when working with large JSON responses

Why this matters

This aligns with expected behavior seen in tools like VS Code, where search navigation keeps results within a comfortable viewing context.

Screenshot

image

Summary by CodeRabbit

  • Bug Fixes
    • Improved code editor search to better center matched lines in the viewport when scrolling to results, enhancing visibility and user experience.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Walkthrough

CodeMirrorSearch's scroll behavior is enhanced to center matching search results in the viewport instead of simply scrolling them into view, addressing issue #7875 through a targeted algorithm that calculates and positions the match line relative to viewport dimensions.

Changes

CodeMirror Search Centering Algorithm

Layer / File(s) Summary
Core Scroll Logic
packages/bruno-app/src/components/CodeMirrorSearch/index.js
Replaces simple scrollIntoView call with centered-scroll algorithm: retrieves active match position via editor.heightAtLine, computes target scroll offset to center the match within viewport bounds, and applies the offset via editor.scrollTo.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • usebruno/bruno#6920: Modifies the same CodeMirrorSearch component and updates scroll-to/current-match behavior alongside this centered-scroll refinement.

Suggested labels

size/M

Suggested reviewers

  • helloanoop
  • lohit-bruno
  • sid-bruno
  • bijin-bruno

Poem

🔍 A search match dances in the viewport wide,
No longer lost at edges, now centered with pride.
CodeMirror scrolls with mathematical grace,
Each find takes its rightful place in the frame's embrace.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: centering the active search match in CodeMirror's viewport, which directly aligns with the changeset's primary improvement.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/bruno-app/src/components/CodeMirrorSearch/index.js`:
- Around line 159-174: The current centering uses
editor.heightAtLine(activeMatch.from.line, 'local') which ignores wrapped-line
offsets; replace that with editor.charCoords(activeMatch.from, 'local') and use
coords.top (the actual on-screen Y for the match) when computing targetScrollTop
so wrapped matches are centered correctly; update the code that defines matchTop
(or remove it) to call editor.charCoords(activeMatch.from, 'local') and use the
returned .top value in the existing centering calculation before calling
editor.scrollTo.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 19325b30-8e23-43ee-8571-d8624726d0f4

📥 Commits

Reviewing files that changed from the base of the PR and between ba42c22 and 61863c3.

📒 Files selected for processing (1)
  • packages/bruno-app/src/components/CodeMirrorSearch/index.js

Comment on lines +159 to +174
const activeMatch = matches[matchIndex];
const scroller = editor.getScrollerElement();
const lineHeight = editor.defaultTextHeight();

// CodeMirror's heightAtLine gives us the vertical position of the line
// inside the full editor document, not just the visible screen.
const matchTop = editor.heightAtLine(activeMatch.from.line, 'local');

// We subtract half the viewport height, then add a few line heights so
// the highlighted line is visually centred instead of being too high.
const targetScrollTop = Math.max(
0,
matchTop - scroller.clientHeight / 2 + lineHeight * 3
);
// my line of work ends here
editor.scrollTo(null, targetScrollTop);
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In CodeMirror 5, what is the difference between heightAtLine(line, 'local')andcharCoords(pos, 'local'), and which API reflects the actual vertical position of a match inside a wrapped line?

💡 Result:

In CodeMirror 5, heightAtLine(line, "local") and charCoords(pos, "local") both accept "local" as the coordinate reference mode, but they answer different geometry questions: 1) heightAtLine(line, "local") - Returns the y position (height from the top of the editor viewport) of the top of the given logical line. - It’s line-level and based on CodeMirror’s internal measurement model for line heights (which can be approximated when the line has not actually been rendered due to viewport/lazy rendering) [1]. - For wrapped lines, this is about the logical line’s top (not a specific visual wrap “sub-line”), so it does not directly tell you where a particular wrapped segment starts/ends. 2) charCoords(pos, "local") - Returns the rectangle for a specific character position in the document, including top/bottom in the chosen coordinate system (here, "local") [2][3]. - Because it’s character-based, it reflects the actual layout of the visual line wrapping for that position (including which wrapped segment the character is on). Which API reflects the actual vertical position of a match inside a wrapped line? - Use charCoords(pos, "local") for match rendering/positioning. Since matches are character ranges (positions) and wrapping is visual/segment-based, the character rectangle returned by charCoords is the API that corresponds to the actual on-screen vertical placement of the match within wrapped lines [2][3]. Important nuance about "local" - There have been historical issues where charCoords(..., "local") could be inconsistent/off by padding (and related fixes landed) [4]. So if you’re comparing to other local measurements (or doing pixel-perfect positioning), you should validate against getScrollInfo()/wrapper padding in your exact setup—but the character-based nature of charCoords remains what makes it the correct choice for “vertical position of a match inside a wrapped line.” [4][2]

Citations:


Use charCoords() to reflect the actual position of wrapped matches.

heightAtLine() returns only the logical line's top, which doesn't account for the actual vertical position of a match within a wrapped line. charCoords() is character-position aware and reflects the true on-screen placement.

🔧 Suggested change
-      const matchTop = editor.heightAtLine(activeMatch.from.line, 'local');
+      const matchTop = editor.charCoords(activeMatch.from, 'local').top;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/bruno-app/src/components/CodeMirrorSearch/index.js` around lines 159
- 174, The current centering uses editor.heightAtLine(activeMatch.from.line,
'local') which ignores wrapped-line offsets; replace that with
editor.charCoords(activeMatch.from, 'local') and use coords.top (the actual
on-screen Y for the match) when computing targetScrollTop so wrapped matches are
centered correctly; update the code that defines matchTop (or remove it) to call
editor.charCoords(activeMatch.from, 'local') and use the returned .top value in
the existing centering calculation before calling editor.scrollTo.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant