Skip to content

feat: add line numbers and horizontal scroll to code blocks#704

Open
hankkyy wants to merge 1 commit into
fathah:mainfrom
hankkyy:feat/code-block-lines
Open

feat: add line numbers and horizontal scroll to code blocks#704
hankkyy wants to merge 1 commit into
fathah:mainfrom
hankkyy:feat/code-block-lines

Conversation

@hankkyy

@hankkyy hankkyy commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Feature

Add line numbers to multi-line code blocks and enable independent horizontal scrolling for long lines.

Changes

AgentMarkdown.tsx

  • showLineNumbers={true} for code blocks with more than one line
  • wrapLines={true} so each line gets its own row with a line number
  • lineNumberStyle — dimmed (#636d83), non-selectable, right-aligned
  • codeTagProps={{ style: { whiteSpace: "pre" }}} — preserves formatting and enables horizontal scroll for long lines

main.css

  • .chat-code-block — added overflow-x: auto for horizontal scroll
  • .chat-bubble-agent .chat-code-block pre/div — added overflow-x: auto
  • .chat-code-block .linenumber — styling for line number column

- AgentMarkdown: enable showLineNumbers (for multi-line blocks),
  wrapLines, line number styling (dimmed, non-selectable), and
  codeTagProps with whiteSpace:pre for proper horizontal scroll
- main.css: add overflow-x:auto to .chat-code-block and code block
  pre/div containers, add .linenumber styling
@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds line numbers to multi-line code blocks and enables independent horizontal scrolling for long lines in the chat's syntax-highlighted code view.

  • AgentMarkdown.tsx: Conditionally enables showLineNumbers and wrapLines when code contains more than one line, applies a lineNumberStyle object, sets whiteSpace: \"pre\" via codeTagProps, and adds overflowX: \"auto\" to customStyle.
  • main.css: Adds overflow-x: auto to both the outer .chat-code-block container and the inner pre/div selector, and introduces a .linenumber CSS rule for the line number gutter styling.

Confidence Score: 4/5

The change is a self-contained UI enhancement with no data-path or security implications; it is safe to merge after addressing the style nits.

The core logic is straightforward and correct. Three issues exist: the outer .chat-code-block gets a redundant overflow-x: auto that fights its existing overflow: hidden; wrapLines is always true even for single-line blocks where the wrapping is unnecessary; and the inline lineNumberStyle object and the new CSS .linenumber rule are exact duplicates, leaving the CSS rule unreachable. None of these cause broken rendering, but the dead CSS rule in particular is a maintenance trap.

Both changed files have minor style/redundancy issues worth cleaning up before merge, with main.css carrying the overflow conflict and AgentMarkdown.tsx carrying the duplicate style definitions.

Important Files Changed

Filename Overview
src/renderer/src/components/AgentMarkdown.tsx Adds line numbers (conditional on multi-line content), wrapLines, lineNumberStyle, overflowX, and codeTagProps to the Prism highlighter. Two style nits: wrapLines should mirror the showLineNumbers condition, and the inline lineNumberStyle object duplicates the new CSS rule, making the CSS dead code.
src/renderer/src/assets/main.css Adds overflow-x: auto to the outer .chat-code-block container (conflicting with the existing overflow: hidden), overflow-x: auto to the inner pre/div selector, and a .linenumber rule that is overridden by the inline styles in AgentMarkdown.tsx.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[CodeBlock renders] --> B{Multi-line code?}
    B -->|yes| C[showLineNumbers=true\nwrapLines=true]
    B -->|no| D[showLineNumbers=false\nwrapLines=true always on]
    C --> E[Prism wraps each line\nin its own span]
    D --> F[Prism renders without\nline number gutter]
    E --> G[lineNumberStyle inline object\napplies gutter styles]
    G --> H[CSS .linenumber rule\nalso present but never wins]
    E --> I[whiteSpace=pre + overflowX=auto\nenables horizontal scroll]
    F --> I
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[CodeBlock renders] --> B{Multi-line code?}
    B -->|yes| C[showLineNumbers=true\nwrapLines=true]
    B -->|no| D[showLineNumbers=false\nwrapLines=true always on]
    C --> E[Prism wraps each line\nin its own span]
    D --> F[Prism renders without\nline number gutter]
    E --> G[lineNumberStyle inline object\napplies gutter styles]
    G --> H[CSS .linenumber rule\nalso present but never wins]
    E --> I[whiteSpace=pre + overflowX=auto\nenables horizontal scroll]
    F --> I
Loading

Reviews (1): Last reviewed commit: "feat: add line numbers and horizontal sc..." | Re-trigger Greptile

Comment on lines 2920 to 2924
.chat-code-block {
border-radius: 6px;
overflow: hidden;
overflow-x: auto;
margin: 6px 0 !important;

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.

P2 overflow: hidden masked by overflow-x: auto

Setting overflow-x: auto immediately after overflow: hidden silently changes the computed value to overflow-x: auto; overflow-y: hidden. The overflow: hidden was placed here to clip children to the border-radius: 6px box (a common CSS idiom). The intent of this PR — scrolling the code area — is already fully satisfied by the overflow-x: auto rule on the inner pre/div selector on line 2969. Because the inner element contains its own overflow, the outer .chat-code-block never actually overflows, making this outer overflow-x: auto redundant. Consider removing the new line here and keeping overflow: hidden intact to preserve the clear original intent.

Comment on lines +111 to +112
showLineNumbers={code.split("\n").length > 1}
wrapLines={true}

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.

P2 wrapLines should be conditional, matching showLineNumbers

wrapLines={true} wraps every source line in an extra <span> block, which adds DOM nodes even for single-line code blocks where showLineNumbers evaluates to false and the line-wrapping spans serve no purpose. Aligning the two props eliminates unnecessary overhead for single-line snippets.

Suggested change
showLineNumbers={code.split("\n").length > 1}
wrapLines={true}
showLineNumbers={code.split("\n").length > 1}
wrapLines={code.split("\n").length > 1}

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +113 to +119
lineNumberStyle={{
minWidth: "2.5em",
paddingRight: "1em",
color: "#636d83",
userSelect: "none",
textAlign: "right",
}}

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.

P2 Duplicate line-number styles — inline wins, CSS becomes dead code

The five properties declared in lineNumberStyle (minWidth, paddingRight, color, userSelect, textAlign) are identical to the properties in .chat-code-block .linenumber added in main.css. React inline styles have higher specificity than any CSS class rule, so the CSS rule is effectively unreachable and will never be applied. Consider picking one approach — either keep the inline lineNumberStyle and remove the CSS rule, or remove the inline object and rely entirely on the CSS class — to avoid a maintenance footgun where future edits to the CSS silently have no effect.

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.

1 participant