From 075f73d7012b2cda5d346513f1d60e0aedb85cd6 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Sun, 5 Apr 2026 20:47:56 +0200 Subject: [PATCH] fix(web): only allow line selection via gutter click MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace ::before pseudo-element with an actual for line numbers, injected by the Shiki transformer. Only the gutter span has data-line-number, so clicking code text no longer triggers selection. Gutter gets a hover state (opacity 0.4 → 0.8) for affordance. Co-Authored-By: Claude Opus 4.6 (1M context) --- webui2/src/components/code/file-viewer.module.css | 9 ++++++--- webui2/src/components/code/file-viewer.tsx | 11 ++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/webui2/src/components/code/file-viewer.module.css b/webui2/src/components/code/file-viewer.module.css index ee4b6baa72702fb061a2ec1eae0c8e96f239191c..b3d5ce0372a6b8fa696c6dcaa60113144aba5f5d 100644 --- a/webui2/src/components/code/file-viewer.module.css +++ b/webui2/src/components/code/file-viewer.module.css @@ -28,9 +28,8 @@ padding-bottom: 0.5rem; } -/* Line numbers via ::before pseudo-element */ -.line::before { - content: attr(data-line-number); +/* Line number gutter — injected as a by the Shiki transformer */ +.line-number { display: inline-block; width: 3rem; margin-right: 1rem; @@ -39,3 +38,7 @@ user-select: none; cursor: pointer; } + +.line-number:hover { + opacity: 0.8; +} diff --git a/webui2/src/components/code/file-viewer.tsx b/webui2/src/components/code/file-viewer.tsx index 85a6bf88224a75e1aba846d7691eb17c14f1911b..81fe268161f740889d09b45ffaed79f751a544aa 100644 --- a/webui2/src/components/code/file-viewer.tsx +++ b/webui2/src/components/code/file-viewer.tsx @@ -96,7 +96,16 @@ function lineNumberTransformer(): ShikiTransformer { line(node, line) { // Replace Shiki's "line" class with our CSS module class node.properties["className"] = [styles["line"]!]; - node.properties["dataLineNumber"] = line; + // Prepend a gutter for the line number — clickable target + node.children.unshift({ + type: "element", + tagName: "span", + properties: { + className: [styles["line-number"]!], + dataLineNumber: line, + }, + children: [{ type: "text", value: String(line) }], + }); // Append a \n text node so copy-paste preserves newlines // (we strip the inter-element whitespace nodes in code() below). node.children.push({ type: "text", value: "\n" });