Skip to content

Highlight the active line in the code editor - #266

Open
ArthurArthurArthur0817 wants to merge 1 commit into
sysprog21:mainfrom
ArthurArthurArthur0817:feat/active-line-highlight
Open

ArthurArthurArthur0817 wants to merge 1 commit into
sysprog21:mainfrom
ArthurArthurArthur0817:feat/active-line-highlight

Conversation

@ArthurArthurArthur0817

@ArthurArthurArthur0817 ArthurArthurArthur0817 commented Oct 8, 2026 •

Copy link
Copy Markdown

The code editor lacked an active-line indicator, leaving candidates scanning for a thin caret when navigating long snippets or discussing specific line numbers referenced by the interviewer. This made it harder to quickly locate the current row across the editor and the gutter.

When the editor is focused, paintEditor now computes the 0-based active line from a collapsed selection and exposes it to the .editor-stack as an --active-line custom property. The syntax overlay and gutter read this property to position a subtle linear-gradient background behind the text. Moving the caret or scrolling the textarea updates the scroll and line position variables accordingly.

The CSS approach keeps the syntax layer DOM untouched. Inserting markup for the active row would mutate the code overlay, tripping the MutationObserver that guarantees single-pass rendering, and breaking the plain-text nature of the gutter. The highlight is cleared completely when the editor loses focus or when a selection range is active, ensuring it only tracks a collapsed caret.

Testing:
New tests: the DOM contract test verifies the active line tracks the caret when the editor is focused without a selection, asserting the exact caret conditions in the script and the custom properties in the stylesheet. The test was checked by breaking the strict equality it covers and watching it fail.
node --test tests/browser/dom-contract.test.js was run on Windows; against the baseline (with CRLF checked out to LF via dos2unix) this change adds no failure.

Closes #247


Summary by cubic

Highlights the active line in the code editor so candidates can quickly locate the current row while editing or discussing line numbers.

Sets a 0-based --active-line custom property on .editor-stack when the editor is focused with a collapsed caret. The syntax overlay and gutter paint a subtle gradient behind that line, anchored with background-attachment: local so it stays put while scrolling. The highlight clears on blur or while a selection is active. Keeping it in CSS leaves the syntax layer DOM untouched, so the MutationObserver that guarantees single-pass rendering never trips.

Adds an end-to-end test in tests/browser/editor-font-size.test.js verifying the highlight tracks the caret, stays anchored while scrolling, and clears on selection or blur.

Closes #247

Written for commit 59220fe. Summary will update on new commits.

View guided diff

cubic-dev-ai[bot]

This comment was marked as resolved.

jserv

This comment was marked as duplicate.

Comment thread tests/browser/dom-contract.test.js Outdated
Comment thread web/styles.css Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/browser/editor-font-size.test.js">

<violation number="1" location="tests/browser/editor-font-size.test.js:223">
P2: This scroll assertion only rereads `--active-line`, so it passes even if the gradient scrolls away from line 2. Assert the rendered layers’ scroll behavior, such as their `background-attachment`, or measure the painted row after scrolling.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

View guided diff | Re-trigger cubic

assert.equal(
await activeLine(),
"2",
"highlight stays anchored to its row when scrolled natively",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: This scroll assertion only rereads --active-line, so it passes even if the gradient scrolls away from line 2. Assert the rendered layers’ scroll behavior, such as their background-attachment, or measure the painted row after scrolling.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At tests/browser/editor-font-size.test.js, line 223:

<comment>This scroll assertion only rereads `--active-line`, so it passes even if the gradient scrolls away from line 2. Assert the rendered layers’ scroll behavior, such as their `background-attachment`, or measure the painted row after scrolling.</comment>

<file context>
@@ -181,3 +181,72 @@ test("a stored size the page does not offer falls back to the default", async (t
+    assert.equal(
+      await activeLine(),
+      "2",
+      "highlight stays anchored to its row when scrolled natively",
+    );
+
</file context>

jserv

This comment was marked as outdated.

@ArthurArthurArthur0817
ArthurArthurArthur0817 force-pushed the feat/active-line-highlight branch 2 times, most recently from e3b9a64 to 8539578 Compare October 9, 2026 08:42

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

Rebase the current branch onto the upstream default branch and rework the series into functionally minimal commits, folding similar ones and enforcing the project's commit message rules.

@jserv

jserv commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

@ArthurArthurArthur0817 The check run on 8539578 failed in two ways, and only one of them goes away with the rebase.

  1. The new test fails on its first assertion: "highlight tracks a collapsed caret moved by the keyboard" expected --active-line to be 2 and got 1199, the caret line fillLongBuffer left behind. A caret move reaches paintEditor through selectionchange and scheduleEditorPaint (web/interview.js:828 and :3274), which paints on the next animation frame, so reading the property right after keyboard.press sees the previous paint. Wait for the value instead, for example with page.waitForFunction on --active-line, in every assertion that follows a caret move or a scroll.
  2. The theme assertions ("system theme, no stored choice" and the editor colors) fail because the branch predates Let the candidate switch the editor theme #251, which added the light editor theme. After rebasing, check the highlight in that theme too: a fixed rgba(255, 255, 255, 0.06) band is invisible on the light background, so the color needs to come from the theme's own variables.

Also restore the final newline that the diff removes from tests/browser/dom-contract.test.js.

During an interview, candidates often navigate long snippets or
discuss specific line numbers referenced by the interviewer.
Tracking the caret across the editor and gutter without an
active-line indicator makes it harder to locate the current row.

Set a 0-based --active-line CSS custom property on .editor-stack
during paintEditor when the editor is focused with a collapsed
selection, and render a linear-gradient across #editor-highlight
and #editor-lines without mutating the syntax layer DOM.
@ArthurArthurArthur0817

Copy link
Copy Markdown
Author

I have rebased onto the latest upstream/main (resolving conflicts with the new indent guides and scroll tests) and addressed all feedback:

Async Paint Timing in Tests: Integrated page.waitForFunction in editor-font-size.test.js to wait for --active-line to match the expected value before asserting. This resolves the race condition caused by async paint timing after cursor movements and scrolling.

Editor Theme Variable Integration: Replaced hardcoded highlight colors with --code-active-line scoped across themes (#ffffff0f for dark mode, #0000000d for light mode under .editor-stack[data-theme="light"] and the prefers-color-scheme: light media query) to align with PR #251.

I also restored the final newline in tests/browser/dom-contract.test.js.Thanks for the reminder.

@jserv

jserv commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

I have rebased onto the latest upstream/main (resolving conflicts with the new indent guides and scroll tests) and addressed all feedback:

Don't make statements too early. Continue resolving.

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

Rebase latest main branch and resolve conflicts.

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.

Highlight the active line in the code editor

2 participants