From 72d33032f048159630cce41d8cee260779554452 Mon Sep 17 00:00:00 2001 From: cruldra Date: Fri, 25 Sep 2026 01:54:12 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(vscode):=20=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E5=9D=97=E6=82=AC=E5=81=9C=E9=AB=98=E4=BA=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webview-ui/src/codeReader/BlockTree.tsx | 13 +++-- .../webview-ui/src/codeReader/codeReader.css | 48 ++++++++++++++----- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/vscode/webview-ui/src/codeReader/BlockTree.tsx b/vscode/webview-ui/src/codeReader/BlockTree.tsx index c2cef73..c984b58 100644 --- a/vscode/webview-ui/src/codeReader/BlockTree.tsx +++ b/vscode/webview-ui/src/codeReader/BlockTree.tsx @@ -36,19 +36,22 @@ export interface BlockTreeState { onToggleFold: (id: string) => void } -/** 一层代码块:左边一条竖线标出这一层,每块的子块紧跟在它下面、再往右缩进一层。 */ -export function BlockLevel({ blocks, tree }: { blocks: BlockView[], tree: BlockTreeState }): ReactElement { +/** + * 一层代码块:左边一条竖线标出这一层,每块的子块紧跟在它下面、再往右缩进一层。 + * kind 是这一层所属块的种类(顶层没有),悬停那个块时竖线换成它的颜色。 + */ +export function BlockLevel({ blocks, kind, tree }: { blocks: BlockView[], kind?: BlockKind, tree: BlockTreeState }): ReactElement { return ( -
+
-
+
{blocks.map(block => ( {block.children.length > 0 && !tree.collapsed.has(block.id) && ( - + )} ))} diff --git a/vscode/webview-ui/src/codeReader/codeReader.css b/vscode/webview-ui/src/codeReader/codeReader.css index f9cb672..536d1db 100644 --- a/vscode/webview-ui/src/codeReader/codeReader.css +++ b/vscode/webview-ui/src/codeReader/codeReader.css @@ -52,21 +52,27 @@ body.vscode-high-contrast-light { --cr-kind-comment: #008000; } -/* 种类颜色:同一类语义共用一个颜色,标签文字区分具体是哪种 */ -.cr-block[data-kind="import"] { --kind: var(--cr-kind-import); } -.cr-block[data-kind="function"] { --kind: var(--cr-kind-function); } -.cr-block:is([data-kind="class"], [data-kind="type"]) { --kind: var(--cr-kind-type); } -.cr-block:is([data-kind="field"], [data-kind="const"], [data-kind="variable"]) { --kind: var(--cr-kind-data); } -.cr-block:is([data-kind="if"], [data-kind="else"]) { --kind: var(--cr-kind-branch); } -.cr-block[data-kind="loop"] { --kind: var(--cr-kind-loop); } -.cr-block:is([data-kind="try"], [data-kind="catch"], [data-kind="finally"]) { --kind: var(--cr-kind-error); } -.cr-block[data-kind="return"] { --kind: var(--cr-kind-return); } -.cr-block[data-kind="statement"] { --kind: var(--cr-kind-statement); } -.cr-block[data-kind="comment"] { --kind: var(--cr-kind-comment); } +/* 种类颜色:同一类语义共用一个颜色,标签文字区分具体是哪种。卡片取自己的种类,子层取所属块的种类 */ +[data-kind="import"] { --kind: var(--cr-kind-import); } +[data-kind="function"] { --kind: var(--cr-kind-function); } +:is([data-kind="class"], [data-kind="type"]) { --kind: var(--cr-kind-type); } +:is([data-kind="field"], [data-kind="const"], [data-kind="variable"]) { --kind: var(--cr-kind-data); } +:is([data-kind="if"], [data-kind="else"]) { --kind: var(--cr-kind-branch); } +[data-kind="loop"] { --kind: var(--cr-kind-loop); } +:is([data-kind="try"], [data-kind="catch"], [data-kind="finally"]) { --kind: var(--cr-kind-error); } +[data-kind="return"] { --kind: var(--cr-kind-return); } +[data-kind="statement"] { --kind: var(--cr-kind-statement); } +[data-kind="comment"] { --kind: var(--cr-kind-comment); } +/* 卡片和它的子层是相邻兄弟,:hover 只落在鼠标下最里面那张卡片上,父卡片不跟着亮 */ .cr-block { background: color-mix(in srgb, var(--kind) 7%, transparent); border: 1px solid color-mix(in srgb, var(--kind) 35%, transparent); + transition: background-color 100ms ease-out, border-color 100ms ease-out; +} +.cr-block:hover { + background: color-mix(in srgb, var(--kind) 14%, transparent); + border-color: var(--kind); } .cr-block[data-kind="comment"] { border-style: dashed; @@ -75,6 +81,26 @@ body.vscode-high-contrast-light { background: var(--vscode-editor-background); border-color: var(--vscode-focusBorder); } +.cr-block[data-editing]:hover { + background: color-mix(in srgb, var(--kind) 7%, var(--vscode-editor-background)); +} + +/* 层级竖线:悬停一个块时,它子层的竖线换成它的种类色,标出这个块管到哪里为止 */ +.cr-guide { + background: var(--vscode-editorIndentGuide-background1); + transition: background-color 100ms ease-out; +} +.cr-block:hover + .cr-level > * > .cr-guide { + background: var(--kind); +} + +@media (prefers-reduced-motion: reduce) { + .cr-block, + .cr-guide { + transition: none; + } +} + .cr-badge { color: var(--kind); background: color-mix(in srgb, var(--kind) 18%, transparent);