Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d77e9e8
feat(windows): align default theme with IntelliJ New UI palette
yangboxuan726 Aug 19, 2026
d98de77
chore(windows): vendor IntelliJ platform icons for the icon funnel
yangboxuan726 Aug 19, 2026
d5cac7f
feat(windows): render IntelliJ icons through the app icon funnel
yangboxuan726 Aug 19, 2026
4015181
chore(windows): map long-tail icons and record complete fallback inve…
yangboxuan726 Aug 19, 2026
2509390
test(windows): keep lucide assertions on icons still using lucide
yangboxuan726 Aug 19, 2026
996f007
fix(windows): render IntelliJ icon assets with an svg root
yangboxuan726 Aug 19, 2026
36a6cea
feat(windows): style editor tabs with IntelliJ underline selection
yangboxuan726 Aug 19, 2026
a03e0d7
feat(windows): use IntelliJ blue selection for sidebar rows and rail
yangboxuan726 Aug 19, 2026
8f32100
feat(windows): tighten file tree rows to IntelliJ chrome density
yangboxuan726 Aug 19, 2026
d2ae13a
feat(windows): tighten popup chrome to IntelliJ menu density
yangboxuan726 Aug 19, 2026
3a03832
chore(windows): vendor IntelliJ file type icons as idea-icons theme
yangboxuan726 Aug 19, 2026
94c8435
feat(windows): register the idea-icons bundled file theme
yangboxuan726 Aug 19, 2026
5000fea
Merge remote-tracking branch 'upstream/preview/0.3.0' into feat/windo…
yangboxuan726 Aug 19, 2026
520f3c7
feat(windows): make IDEA icons the default file theme
yangboxuan726 Aug 19, 2026
328285d
feat(windows): add semantic IDEA project icons
yangboxuan726 Aug 20, 2026
c974488
style(windows): polish IDEA-inspired workbench chrome
yangboxuan726 Aug 20, 2026
229beea
docs(windows): record IDEA UI polish scope
yangboxuan726 Aug 20, 2026
7d4257b
Merge remote-tracking branch 'upstream/preview/0.3.0' into feat/windo…
yangboxuan726 Aug 20, 2026
b8454d9
Merge branch 'preview/0.3.0' into feat/windows-idea-ui-polish
1lck Aug 20, 2026
642f57f
Merge branch 'preview/0.3.0' into feat/windows-idea-ui-polish
1lck Aug 21, 2026
8cf4c63
fix(windows): bound Java icon source reads
yangboxuan726 Aug 21, 2026
9bb1f62
Merge branch 'preview/0.3.0' into feat/windows-idea-ui-polish
1lck Aug 21, 2026
743a9db
Merge upstream preview/0.3.0 into feat/windows-idea-ui-polish
yangboxuan726 Aug 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
69 changes: 69 additions & 0 deletions docs/windows-idea-ui-audit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Windows UI 打磨审计

> 基线:`520f3c77 feat(windows): make IDEA icons the default file theme`。
> 日期:2026-08-20。
> 用途:记录正式打磨的基础与校正结果。Windows IDEA 2025.2.1 是对应功能的主视觉参考;Mac Lithe 仅借鉴成熟细节;不做整窗复刻。

## 1. 已完成的基础

### 默认文件图标主题

- `defaultSettings.iconTheme` 已是 `idea-icons`(`windows/tauri/src/features/settings/config/default-settings.ts`)。
- 旧 Lithe 图标主题 ID 会迁移到 `idea-icons`;旧 Material/Seti 别名按现有规则归一化(`windows/tauri/src/features/settings/lib/settings-normalization.ts`)。
- bundled 注册保留 IDEA、Material、Pierre、Symbols,不再注册旧 Lithe 图标主题(`windows/tauri/src/extensions/bundled/bundled-extension-manifests.ts`)。
- 对应默认值、迁移和 manifest 注册已有测试覆盖。
- foundation 提交时已记录通过 186 个前端测试、typecheck、production build、Windows boundary、Release build 和 69 个 Tauri Rust tests;正式打磨后的结果必须重新验证,不能沿用这组结论。

### IDEA 资产通路

- 文件图标 manifest 已包含常用扩展名、文件名、通用文件和文件夹的明暗 IDEA SVG(`windows/tauri/src/extensions/bundled/icon-themes/idea/extension.json`)。
- bundled 资产解析器已能加载 IDEA 图标主题(`windows/tauri/src/extensions/icon-themes/bundled-icon-theme-assets.ts`)。
- 通用操作图标已有生成资产表与统一 `icons.tsx` 入口,能够在明暗主题间选择 IDEA 变体,并保留 Lucide fallback(`windows/tauri/src/ui/icons/idea-assets.generated.ts`、`windows/tauri/src/ui/icons.tsx`)。
- Maven 项目图标(`pom.xml`)的生成器 source 位于 intellij-community 的 `plugins/maven/...` 目录(`idea-file-icon-mappings.json` 的 source/asset 分离机制);本地稀疏克隆需包含该目录才能跑生成器 `--check` 复现校验。

### IDEA 风格基础色板

- `lithe-dark` 已采用 `#1e1f22` 背景、`#2b2d30` 表面、`#43454a` 边框、`#2e436e` 选中和 `#3574f0` 主色等 IDEA 风格令牌;亮色变体也已有对应层级(`windows/tauri/src/extensions/themes/builtin/lithe.json`)。
- `lithe-dark` 语法色已整体换成 New Darcula 系(橙关键字/青数字/绿字符串等),编辑器 selection `#214283`、光标 `#ced0d6`;Monaco 的行高亮与失焦选区已与选中色解耦(`monaco/theme.ts`)。
- `theme.css` 已通过语义变量向组件提供 background、surface、border、selected、primary 等颜色,后续应继续走令牌,不在组件散落 raw hex。

## 2. 当前主要差距

| 区域 | 当前状态 | 本轮动作 |
| --- | --- | --- |
| 图标一致性 | IDEA 文件主题、Java 声明节点、标准 Maven root/package 和操作资产已接入;文件树与 editor tab 共用 Java 语义,不能确认时仍回退通用图标 | 保持可见行/已打开 buffer 的浅词法与真实 `pom.xml` 约束;不按文件名猜类型,不建立全量索引 |
| Project 树 | 已有虚拟化、Compact Folders、git 状态和主题图标入口;source root 会截断 compact,package 仅改变显示名与图标;层级 guide 静止透明、靠近或键盘聚焦时显现 | 保持 row-model 投影与 guide 原命中几何;selection、rename、watcher、路径操作继续使用真实路径 |
| 主工具栏 | Project、branch、Quick Open、更新和窗口控制均有真实 action;中文紧凑菜单已禁止收缩换行 | 只调整视觉分组;不放禁用运行选择器或重复项目入口 |
| Project tabs | 完整切换/关闭/拖拽逻辑存在,单项目已隐藏 | 多项目保留独立紧凑行,避免重写状态或强塞主工具栏 |
| Workbench | `lithe-glass-island`、resize 和透明逻辑是成熟结构;Project/editor 统一使用 `background` token,并保留中间左右边线、真实 4px gutter 与 resize handle;主工作区顶/底外沿不描线;editor/BottomPane 四角使用同一半径,与右侧 rail 无 gap、无相邻双边线 | 保留轻圆角容器、内容宽度和 resize 行为,只校准 gap、分隔、圆角与表面层级 |
| Editor tabs | 交互能力较多,视觉上仍偏厚、图标与关闭态不够统一 | 只改高度、激活线、hover、图标槽和边框,完整保留 tab 行为 |
| Activity rail | 左 rail 承担真实路由;右侧恢复 38px Extensions rail,并与左 rail 共用 `surface` 颜色;唯一 Puzzle 按钮打开真实 singleton Extensions buffer,active 跟随当前 buffer | 只显示已有真实 action;预留空白不等于预造未来按钮,保持紧凑中性选中态 |
| Bottom pane | Terminal、Run、Git Log、Debugger、Buffers 共用容器;Terminal 最后一个 session 关闭时会自动收起,其他工具窗不受影响 | 只识别同 workspace 的 terminal 数量 `>0 → 0` 且当前可见 tab 为 Terminal;全局新建入口必须重新展开并仅创建一次 |
| Tool window header | 各 feature 的标题和动作排布不完全一致,Project 区的层级感不足 | 建立或复用统一 presentation 原语,不改变各 feature action |
| Status bar | 已组件化且支持排序,但文字、chip、图标和间距不在同一密度体系 | 统一度量并重点检查 zh-CN 长文案和窄窗口容量 |
| 字体与语言 | 新默认已为 Microsoft YaHei UI 13 与 `zh-CN`;仅成对迁移旧 Geist Sans 15 默认值 | 保留用户显式选择,验证中文、大字号和 Windows 125% 缩放 |

## 3. 明确不做

- 不复刻 IDEA 2025.2.1 的全部布局、交互或 Ultimate 专有功能。
- 不建立完整 Java AST、Maven/Gradle Project Model、持久化语义缓存、后台全树索引或 sidecar;仅允许有界的可见行浅词法识别和已加载标准 Maven 路径投影。
- 不修改 Tauri 命令、platform dispatcher、shared contracts、Rust Core 或 macOS。
- 不新增字体或 SVG 转换依赖来解决现有 CSS/资产通路已经能完成的问题。
- 不要求 2px 像素误差、透明叠图、固定九张证据图或五次启动统计。
- 不把本机的 `intellij-community`、示例项目或截图绝对路径写入产品代码。

## 4. 风险与护栏

- **全局令牌影响所有主题。** `theme.css` 中的结构变量可以共享,IDEA 专属颜色必须留在 Lithe 主题;每轮至少 smoke 一个非 Lithe 暗色主题和一个亮色主题。
- **UI 密度会暴露中文容量问题。** 主工具栏、Project tabs、状态栏和设置弹窗需在常规/较窄窗口及 125% 缩放下检查;树行随用户字号增长,不能为了紧凑裁字。
- **图标同名不等于同义。** 返回/前进、上下移动、展开/收起、运行/调试和关闭类资产需要逐个看 SVG;不能让 `mirrored` 再次反转已有方向。
- **presentation 重排容易误伤行为。** 项目切换、tab DnD/固定/预览、rail 路由、pane resize 和窗口拖动依赖现有组件;样式改动前后用现有测试与人工清单对照。
- **点击区不能随视觉尺寸一起缩没。** 图标可以更紧凑,交互 hitbox、键盘焦点和可访问名称必须保留。

## 5. 完成判据

- 用户认可中文 Dark 主窗口的整体质感,并认为已达到“参考 IDEA New UI 打磨后的 Lithe”,无需与 IDEA 像素一致。
- 主工具栏、Project 树、editor tabs、activity rail、tool-window header 和 status bar 形成同一套视觉语言。
- 文件图标和常用操作图标语义正确,IDEA Icons 默认生效,其他显式图标主题仍可使用。
- 中文常规/窄窗口不破版,Light、English 和第三方主题完成 smoke。
- `bun test`、typecheck、production build、Windows boundary、Release build 和 Tauri Rust tests 均通过;未执行项如实披露。
91 changes: 91 additions & 0 deletions docs/windows-idea-ui-polish-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Windows 端 IDEA New UI 风格打磨方案

> 状态:已获准正式开发,2026-08-20 按“现有功能逐项效仿”口径校正。
> 参考:Windows IntelliJ IDEA 2025.2.1 是主视觉标准;Mac Lithe 截图只借鉴已经验证成熟的局部呈现;本地 `intellij-community` 提供主题与 SVG 资产。它们不是整窗克隆规范。

## 1. 目标与边界

- 只打磨 Windows React/Tauri 产品,macOS 不动。
- 中文界面优先,Dark 先完成;Light 与 English 只做不破版检查。
- 目标是让 Lithe 的主窗口明显具备 IDEA New UI 的图标语言、表面层级、密度和控件质感,同时保留 Lithe 的名称、Logo、多项目能力和已有功能入口。
- 允许调整 `windows/tauri/src/features/**/components`、对应样式以及 `windows/tauri/src/ui` 中的呈现壳和可复用原语。
- 功能、状态模型、数据流、持久化和现有交互不变;不改 `platform` 调度、Tauri 命令、`shared` 契约、Rust Core 或 macOS 实现。
- 先确认 Windows 已有真实功能,再寻找 Windows IDEA 对应 UI;没有功能就不显示按钮、占位入口或空工具窗。Mac 端仅在相同功能已有更成熟落法时作为补充参考。
- 不为图标显示新增完整 Java 解析器、持久化语义索引、sidecar 或 Project Model。IDEA Icons 可对虚拟列表中实际显示的 Java 文件及已经打开的 editor buffer 做有界浅词法识别,并从已加载且含 `pom.xml` 的标准 Maven 目录结构投影 source root/package;声明名不匹配、读取失败或结构不标准时回退通用图标。
- 优先复用现有依赖和图标漏斗。只有现有栈确实无法完成时才考虑新依赖,并单独说明必要性与体积影响。

## 2. 视觉参考与资产规则

- Windows IDEA 2025.2.1 截图用于对应功能的观感对照:工具栏层级、Project 树密度、编辑器标签、侧边工具窗、分隔线、选中态和状态栏。Mac Lithe 不决定 Windows 布局,只提供可选的产品细节。
- `intellij-community` 用于查找开源的 IDEA SVG、明暗变体和主题色。不得在运行时代码中写入本机仓库路径,也不照搬 Swing/Kotlin 实现。
- SVG 进入仓库时保留上游文件内已有的版权信息,通过现有 IDEA 资产生成器和 `icons.tsx` 漏斗接入;不用同名猜语义,方向图标要核对前进/后退、展开/收起和 `mirrored` 约定。
- IDEA Icons 作为默认文件图标主题;Material、Pierre、Symbols 等显式选择继续保留。
- 颜色、尺寸和状态值集中在主题令牌或共享 UI 原语中。业务组件不得散落 IDEA 色值和重复魔法数字。
- 主题决定颜色,结构样式决定布局。调整结构令牌时必须检查其他 bundled 主题,不能让第三方配色主题意外继承 IDEA 专属颜色。

## 3. 实施顺序

### A. 图标与 Project 树

- 补齐主工具栏、常用操作、activity rail、Project 树和编辑器标签实际用到的 IDEA SVG 映射。
- 统一 16px 图标槽、展开箭头、目录开合、文件类型、悬停与选中状态。
- 调整 Project 树的行高、缩进、文字基线、选中背景、工具窗标题和右侧操作按钮。
- 保留 Project 树层级 guide 的原有命中区与折叠行为;静止时保持透明,鼠标靠近 guide 区或键盘 `focus-visible` 位于树内时淡入,不允许为显线改变缩进几何。
- Java `class/interface/enum/@interface/record` 只在浅词法结果与文件 basename 严格一致时使用对应图标;Exception 只认显式直接继承 Java 内建异常基类。磁盘只读取虚拟列表实际挂载的行,editor tab 只消费已打开 buffer,不扫描全树;不能确认时保持 Java 通用图标。
- 标准 Maven `src/main/java`、`src/test/java`、resources roots 及合法 package 路径由已加载树中的真实 `pom.xml` 约束;Compact Folders 不得跨 source root 合并,selection、rename、watcher 和文件操作继续使用真实路径。

### B. 主题令牌与通用原语

- 继续使用已经落地的 IDEA 风格暗色色板,校准背景/表面层级、边框、分隔线、悬停、选中和焦点态。
- Project 文件区与 editor 使用同一个 `background` 主题令牌;两者之间保留 token border 与 workbench gap,主工作区顶/底外沿不额外描线;editor 与右侧 Extensions rail 直接衔接,不用双边框或空隙制造层级。
- 统一工具栏按钮、图标按钮、tabs、列表行、弹层和 resize 分隔条的高度、圆角及视觉 padding。
- 点击热区可以大于图标本身,但不能靠额外可见 padding 把界面重新撑松。
- 字体以 Windows 中文清晰度和可靠 fallback 为先,不为追求英文截图外观盲目增加字体包。

### C. 主窗口 chrome

- 主工具栏:只放真实的菜单、Project、branch、Quick Open、更新和窗口控制;不复制不存在的运行选择器或重复项目入口。
- Project tabs:这是 Lithe 的真实多项目能力;单项目隐藏,多项目保留独立紧凑行,不为了像 IDEA 强塞进主工具栏。
- Workbench:保留现有可调整大小的轻圆角面板结构;Project 与 editor 之间继续使用左右 token border 和既有 workbench gap,resize handle 留在 gap 内;主工作区顶/底外沿不绘制横线。editor 与 BottomPane 使用完整 `rounded-xl`,右上/右下与左侧采用同一半径;它们与右侧 Extensions rail 直接相邻,不画相邻边线,也不在两者之间留 gap。只收紧外缝、层级和分隔,不为追求截图拆掉成熟容器或重排业务挂载点。
- Editor tabs:统一高度、激活下划线、文件图标、关闭按钮和 hover 状态;拖拽、固定、预览、脏标记、键盘和跨窗行为不变。
- Activity rail / tool-window header:左 rail 保持现有真实路由;右侧固定预留 38px Extensions rail,并与左 rail 使用同一个 `surface` 颜色,目前只放一个能打开真实 singleton Extensions 页面的 Puzzle 按钮。未来只有存在真实 action 时才增加按钮。统一尺寸、选中反馈、标题与现有动作排列。
- Status bar:统一高度、间距、文字层级与图标,检查中文长文案和项目状态容量,避免同一状态在顶部与底部无意义重复。
- Bottom pane:关闭最后一个 terminal 后自动收起 Terminal pane;重新从 activity rail、菜单或命令面板新建时再展开且只创建一个。Run、Git Log、Debugger 与 Buffers 不受 terminal 归零影响。

## 4. 开发纪律

- 一个总 PR,按“图标与文件树 → 令牌/原语 → 顶部 chrome/tabs → rail/tool window/status bar → 集成收口”分层提交。
- 每层提交保持应用可运行;保留相关行为测试,不用大范围快照替代功能断言。
- 呈现组件继续调用现有 feature actions/stores,不从 view 直接调用 Tauri API,不新增跨层快捷通道。
- 不做无关重构、依赖升级或生成物提交;不硬编码本机项目、工具安装或截图路径。
- 若某项“更像 IDEA”的改法会改变用户行为或跨越边界,先停在现状,不在 UI 打磨中顺手重设计。
- capability 不可用或没有渲染消费者的入口必须隐藏;不得用永久 disabled 控件表达未来功能。

## 5. 验收方式

视觉验收以中文 Dark 主窗口为主,不设逐像素误差或固定截图数量。使用同一个真实项目打开文件树和若干编辑器标签,与 IDEA 参考图并排查看:

- 第一眼能识别为同一类 New UI 视觉语言,且仍然是 Lithe。
- 工具栏、Project 树、editor tabs、activity rail、tool-window header 和 status bar 的密度、层级、图标风格一致。
- 常规窗口与较窄窗口无重叠、无不可达操作、无中文截断;125% Windows 缩放下显示正常。
- Dark 为完整验收;Light、主题切换和 English 各做一次 smoke;Material、Pierre、Symbols 仍可选择。
- 人工回归项目切换/溢出、文件树展开与选中、tab 打开/关闭/重排/固定、rail 切换、pane resize、窗口拖动和状态栏显示。
- 最终效果由用户查看实机截图或运行版本后确认。

## 6. 验证矩阵

迭代时运行最小相关测试、`bun test` 和 `bun run typecheck`。总 PR 收口前在 Windows 完成:

```powershell
Set-Location windows/tauri
bun test
bun run typecheck
bun run build

Set-Location ../..
./scripts/verify-windows-boundaries.ps1
./scripts/build-windows.ps1 -Configuration Release
cargo test --manifest-path windows/tauri/src-tauri/Cargo.toml
```

任何未实际执行的检查都必须在交付说明中明确列出,不能按通过报告。
60 changes: 59 additions & 1 deletion scripts/build-windows.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@ param(
$ErrorActionPreference = "Stop"
$root = Split-Path -Parent $PSScriptRoot
$windowsApp = Join-Path $root "windows/tauri"
$bundledExtensionsSource = [System.IO.Path]::GetFullPath((Join-Path $windowsApp "src/extensions/bundled"))
$preparedJdtlsRoot = $null
if (-not (Test-Path -LiteralPath $bundledExtensionsSource -PathType Container)) {
throw "Bundled extensions source directory is missing: $bundledExtensionsSource"
}
if ($Configuration -eq "Release") {
& (Join-Path $root "scripts/prepare-jdtls.ps1") | Out-Null
$prepareOutput = @(& (Join-Path $root "scripts/prepare-jdtls.ps1"))
if ($prepareOutput.Count -eq 0) {
throw "JDTLS preparation did not return an output directory."
}
$preparedJdtlsRoot = [System.IO.Path]::GetFullPath([string]$prepareOutput[-1])
}
Set-Location $windowsApp

Expand Down Expand Up @@ -40,4 +49,53 @@ if ($Configuration -eq "Debug") {
& bunx @tauriArgs
if ($LASTEXITCODE -ne 0) { throw "Windows Tauri build failed" }

$profileName = if ($Configuration -eq "Debug") { "debug" } else { "release" }
$cargoTargetRoot = [System.IO.Path]::GetFullPath((Join-Path $windowsApp "src-tauri/target"))
$profileRoot = [System.IO.Path]::GetFullPath(
(Join-Path (Join-Path $cargoTargetRoot $RustTarget) $profileName)
)
$trimCharacters = [char[]]@([System.IO.Path]::DirectorySeparatorChar, [System.IO.Path]::AltDirectorySeparatorChar)
$targetPrefix = $cargoTargetRoot.TrimEnd($trimCharacters) + [System.IO.Path]::DirectorySeparatorChar
if (-not $profileRoot.StartsWith($targetPrefix, [System.StringComparison]::OrdinalIgnoreCase)) {
throw "Windows Cargo target profile must stay inside $cargoTargetRoot"
}
if (-not (Test-Path -LiteralPath (Join-Path $profileRoot "lithe-windows.exe") -PathType Leaf)) {
throw "Windows Tauri executable is missing from target profile: $profileRoot"
}

function Copy-ResourceDirectory {
param([string]$Source, [string]$RelativeDestination)

if (-not (Test-Path -LiteralPath $Source -PathType Container)) {
throw "Bundled resource source directory is missing: $Source"
}
$destination = [System.IO.Path]::GetFullPath((Join-Path $profileRoot $RelativeDestination))
$profilePrefix = $profileRoot.TrimEnd($trimCharacters) + [System.IO.Path]::DirectorySeparatorChar
if (-not $destination.StartsWith($profilePrefix, [System.StringComparison]::OrdinalIgnoreCase)) {
throw "Bundled resource destination must stay inside target profile: $destination"
}
if (Test-Path -LiteralPath $destination) {
Remove-Item -Recurse -Force -LiteralPath $destination
}
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $destination) | Out-Null
Copy-Item -Recurse -Force -LiteralPath $Source -Destination $destination
$destination
}

$bundledExtensionsDestination = Copy-ResourceDirectory $bundledExtensionsSource "extensions/bundled"
foreach ($relativePath in @("icon-themes", "themes", "icon-themes/idea/extension.json")) {
if (-not (Test-Path -LiteralPath (Join-Path $bundledExtensionsDestination $relativePath))) {
throw "Bundled extensions staging is incomplete: $relativePath"
}
}

if ($Configuration -eq "Release") {
$jdtlsDestination = Copy-ResourceDirectory $preparedJdtlsRoot "LanguageServers/jdtls"
foreach ($relativePath in @("bin/jdtls.bat", "config_win", "plugins")) {
if (-not (Test-Path -LiteralPath (Join-Path $jdtlsDestination $relativePath))) {
throw "Bundled JDTLS staging is incomplete: $relativePath"
}
}
}

Write-Output "Windows Tauri build completed."
Loading
Loading