diff --git a/docs/design-system.md b/docs/design-system.md new file mode 100644 index 0000000..a06fe09 --- /dev/null +++ b/docs/design-system.md @@ -0,0 +1,178 @@ +# ok-script-toolkit · 全局 UI 统一设计规范 + +> 本文件是全项目 UI 的唯一权威规范。所有 webview 面板(console / templatePanel / +> templateAssetPanel / tempScreenshots / annotationPanel / characterManager)必须遵循。 +> 实现真源:`media/shared/tokens.css`(Design Tokens)+ `media/shared/controls.css`(共享控件), +> **页面只负责组合这些类,不得自行重定义视觉规则。** + +## 0. 核心要求 + +> **不是把每个页面分别做得好看,而是让整个 UI 看起来像由同一套设计系统设计出来的。** + +--- + +## 1. 统一设计语言 + +必须建立并遵循统一 Design System,覆盖:页面背景 / 容器背景 / 卡片 / 按钮 / 输入框 / +下拉框 / Checkbox·Radio·Switch / Tab / 标签 / 列表 / 分隔线 / 图标 / Tooltip / +Dialog·Modal / 状态提示 / Loading / 空状态 / 错误状态。同类组件必须使用同一种视觉语言。 + +## 2. 统一颜色体系 + +统一颜色层级(页面背景 > 一级容器 > 控件面 > Hover/Active),不得按组件单独定义颜色。 + +| 语义 | Token | 说明 | +|---|---|---| +| 页面背景 | `--bg-page` | 最底层 | +| 一级容器 | `--bg-container` / `--bg-container-raised` | 面板 / 卡片 | +| 控件面(真按钮) | `--bg-control` | Button / IconButton 的**默认**底色(配描边) | +| 行级面(组头、折叠标题行) | `--bg-row` | 行级可点击区的极浅底色——默认可识别但不与按钮同权重 | +| Hover / Active | `--bg-control-hover` / `--bg-control-active` / `--bg-row-hover` / `--surface-hover` | 交互态 | +| 边框 | `--border` / `--border-strong` | 常规 / 聚焦 | +| 主文字 | `--text-primary` | | +| 次要文字 | `--text-muted` | | +| 禁用文字 | `--text-disabled` | | +| 语义色 | `--ok` / `--run` / `--warn` / `--pause` / `--err` | 禁止另造色值 | + +**禁止**:页面/组件直引 `--vscode-*` 变量(仅 `tokens.css` 允许)、硬编码 hex/rgba。 + +## 3. 所有可点击控件统一表现 + +可点击控件**默认状态**即须有明确可点击表现: + +- ❌ 默认只是普通文字 / ❌ 默认与容器融为一体 / ❌ 只有 Hover 后才出现背景 +- ✅ 默认即有底色,Hover 是**增强**,不承担「让用户第一次发现这是按钮」的职责 + +**两类控件分层**(避免整屏层层方块): + +| 类别 | 用法 | 默认态 | +|---|---|---| +| 真按钮 | 动作类:保存/同步/重置/启用/关闭/图标按钮 | `background: var(--bg-control)` + `border: 1px solid var(--border)` | +| 行级可点击区 | 组头、折叠标题行、列表内的可点击行 | `background: var(--bg-row)`(极浅色调)+ **无描边**,Hover 用 `--bg-row-hover` | + +同类按钮须一致:高度(`--control-h-sm/md/lg`)、内边距(`--space-*`)、字体、圆角 +(`--radius-*`)、边框、背景、图标尺寸、图标与文字间距、Hover/Active/Focus/Disabled。 + +## 4. 统一尺寸体系 + +- 间距:`--space-xs(4) / sm(6) / md(10) / lg(14) / xl(20)` +- 控件高度:`--control-h-sm(24) / md(30) / lg(34)` +- 圆角:`--radius-sm(5) / md(8) / lg(11) / pill` +- 字号:`--font-xs(11) / sm(12) / md(13) / lg(15)`;字重仅 `--weight-regular(400)` / `--weight-medium(500)` + +禁止无依据的 32/35/38/30px 按钮高度混用,禁止 4/6/10/不圆的圆角混用。 + +## 5. 统一 Typography + +字体继承 `--vscode-font-family`;层级:页面标题 / Section 标题(`.panel-section-title`)/ +正文 / 辅助文字(`.panel-hint`) / Label / Button Text / Caption / Error·Warning Text。 +字重仅 400 / 500。 + +## 6. 统一圆角、边框和阴影 + +- Border Radius:仅 `--radius-sm/md/lg/pill` +- Border Width:`--border-width`(1px);Border Color:`--border` / `--border-strong` +- Shadow:仅 `--shadow`,且仅用于浮层(抽屉 / 弹窗 / 悬浮卡) + +## 7. 统一交互状态 + +所有交互组件遵循:`Default / Hover / Active / Focus / Disabled / Loading`。 +`Focus` 必须用 `--border-strong` 或 outline 呈现;`Disabled` 统一 `opacity: .45` + `not-allowed`。 + +## 8. 同功能必须使用同组件 + +保存 / 取消 / 删除 / 添加 / 编辑 / 刷新 / 设置 / 关闭 / 确认 → 复用共享 Button·IconButton; +输入框 → 统一 Input;下拉 → 统一 Select;弹窗 → 统一 Dialog;标签 → 统一 Tag; +提示 → 统一 Toast·Alert;开关 → 统一 Switch。**优先复用现有组件,而不是复制 CSS。** + +## 9. 统一布局 + +页面边距、内容最大宽度、Section 间距、Header 高度、Toolbar 高度(`.panel-toolbar`)、 +卡片间距、Dialog 布局、操作区布局保持一致;跨页面切换应感觉属于同一应用。 + +## 10. 不允许局部「特立独行」 + +消除:按钮特别大 / 没有边框 / Hover 才出现背景 / 不同圆角 / 不同字体 / 不同颜色体系 / +同功能不同外观 / 相同组件多套实现。无明确 UX 理由不得为单页面创造特殊样式。 + +## 11. 设计系统资产 + +``` +media/shared/tokens.css Colors · Typography · Spacing · Radius · Border · Shadow · Sizes +media/shared/controls.css Button(主/次/迷你/幽灵/图标) · Input · Select · Checkbox/Switch + · Tag · Card · Toolbar · SectionTitle · Empty/Broken/Hint · Divider + · 可点击性硬规范([role=button]、真按钮/行级区分层清单) +``` + +新增面板接入方式(**三步,缺一步样式就静默失效**): + +1. `index.html` 按顺序引入 `__SHARED_TOKENS_URI__` → `__SHARED_CONTROLS_URI__` → 面板自身样式 + (顺序即层叠优先级:面板可以覆盖共享层); +2. 宿主 `buildHtml` 用 `applySharedAssets(webview, extensionUri, html)` 替换两个占位符 + (`src/webviewHtml.ts`,唯一实现;不要在面板里再抄一份 `asWebviewUri` 组装); +3. `localResourceRoots` 若没有放行整个 `extensionUri`,必须补 `sharedResourceRoot(extensionUri)` + (收紧到 `media/<面板>` 的面板否则加载不到 shared 资源)。 + +**自动审计**:`node scripts/test_design_system.js` —— 校验上面三步 + 面板 CSS 无字面量色 / +无 `--vscode-*` 直引 / 圆角字号走 scale / `var()` 全部有定义。 +例外:canvas 绘图色(标注框描边等)属于**图像内容**而非 UI 主题,不受色值约束。 + +## 12. 最终验收标准(全局 UI Audit 清单) + +1. 所有页面使用同一套设计语言 +2. 同类组件视觉一致 +3. 所有可点击控件默认状态即可识别 +4. Hover 不再承担「显示这是按钮」的职责 +5. 没有裸文字按钮 +6. 没有与容器完全融为一体的按钮 +7. 颜色、字体、间距、圆角、边框、阴影统一 +8. 相同功能复用相同组件 +9. 不存在只在某一个页面使用的无必要特殊样式 +10. 从任意页面切换到另一个页面,都应明显感觉属于同一个完整的产品 + +--- + +## 落地进度 + +| 阶段 | 内容 | 状态 | +|---|---|---| +| S1 | 建立 `media/shared/{tokens,controls}.css`;console 接入(视觉零变化,4 个 jsdom 测试守护);宿主 `localResourceRoots` 放行 | ✅ 已完成 | +| S2 | templatePanel / templateAssetPanel 迁移 | ✅ 已完成 | +| S3 | tempScreenshots / annotationPanel 迁移 | ✅ 已完成 | +| S4 | characterManager 迁移(token 别名化 + 基础控件去重 + 标签页/圆角/字号 scale 化) | ✅ 已完成 | +| S5 | 全局 Audit:`scripts/test_design_system.js` 静态审计已就位;剩 i18n 硬编码清理、真实主题截图人工复核 | 🔄 进行中 | + +**六个面板全部接入共享层**(2026-09-23,`feat/sidebar-styling`): +`console` / `templatePanel` / `templateAssetPanel` / `tempScreenshots` / `annotationPanel` / +`characterManager` —— 全部走同一套 token 与控件层。收口成果(自动审计断言): + +| 指标 | 迁移前 | 迁移后 | +|---|---|---| +| 面板 CSS 直引 `--vscode-*` | 6 个文件、共 40+ 处 | **0**(唯一允许处 = `media/shared/tokens.css`) | +| 面板 CSS 字面量色(hex/rgb) | 6 个文件 | **0**(canvas 绘图色除外,见上) | +| 裸 px 圆角 / 字号 | 17 处 / 多处 | **0**(`--radius-*` / `--font-*`) | +| 工具条按钮 | 各自一套 `padding/border/background` | 共享 `.mini-btn` / `.icon-btn` / `.mini-btn.is-active` | + +**迁移踩到的坑(已修)**:`src/webviewHtml.ts` 顶层 `import vscode` 会让 `scripts/` +下的纯函数单测崩在 `Cannot find module 'vscode'` —— 改为类型导入 + 函数体内延迟 +`require`,纯函数保持可独立测试。 + +**已完成的具体整改**(console): +- 「⚙ 参数」按钮:移除 `--warn` 黄色警示语义,全部状态中性化(默认 = 控件面 + 描边; + 已修改 = 描边强化;打开中 = 控件面加深) +- 可点击元素规范(分层,2026-09-23 定案): + - **真按钮** = `--bg-control` + 描边 → 分组折叠按键 / `.btn-mini` / 图标按钮 / 危险按钮 + - **行级可点击区** = `--bg-row` 极浅色调 + 无描边 → 启动设置折叠头 / 任务分组头 / + kind 级组头 / 卡片头 / 未选中分段 tab / 游戏状态行 + - 首版曾把 `--bg-control` 一刀切应用到全部可点击元素,导致侧栏成为层层方块墙 + (用户反馈「好丑」)——按钮与行头是两种权重,不可同色同框 +- `[hidden]` 兜底、折叠状态持久化(uiState)、i18n 六语言键对等 + +**其他面板的具体整改**: +- 缩略图/tile 上的悬浮按钮(`templatePanel.open-btn`、`templateAssetPanel.actions`、 + `tempScreenshots` 卡片操作)**由「仅 hover 可见」改为常驻可见**,底色改控件面 + 描边, + 去掉了 `rgba(0,0,0,.55)+#fff`(浅色主题下是黑块) +- 模态遮罩/投影统一走 `--scrim` / `--shadow-sm` / `--shadow-lg` +- `annotationPanel` 工具条 ↔ 模态按钮改用共享 `.mini-btn`;`characterManager` 移除本地 + `:root` token 定义(保留短别名指向共享 token)、基础 `button/input` 声明去重、标签页 + 改为「未选中浅底色 / 选中控件面」 diff --git a/media/annotationPanel/index.html b/media/annotationPanel/index.html index b22f391..623da08 100644 --- a/media/annotationPanel/index.html +++ b/media/annotationPanel/index.html @@ -3,19 +3,21 @@
+ + - diff --git a/media/annotationPanel/style.css b/media/annotationPanel/style.css index 9e9c41b..19423e8 100644 --- a/media/annotationPanel/style.css +++ b/media/annotationPanel/style.css @@ -1,120 +1,89 @@ - * { box-sizing: border-box; margin: 0; padding: 0; } - body { - color: var(--vscode-editor-foreground); - background: var(--vscode-editor-background); - font-family: var(--vscode-font-family); - font-size: var(--vscode-font-size, 13px); - overflow: hidden; - height: 100vh; - display: flex; - flex-direction: column; - } - .toolbar { - display: flex; - align-items: center; - gap: 6px; - padding: 6px 10px; - border-bottom: 1px solid var(--vscode-panel-border); - flex-shrink: 0; - flex-wrap: wrap; - } - .toolbar button { - padding: 4px 10px; - border-radius: 3px; - border: 1px solid var(--vscode-button-secondaryBackground, rgba(128,128,128,.3)); - background: var(--vscode-button-secondaryBackground); - color: var(--vscode-button-secondaryForeground); - cursor: pointer; - font-size: 12px; - white-space: nowrap; - } - .toolbar button:hover { background: var(--vscode-button-secondaryHoverBackground); } - .toolbar button.active { - background: var(--vscode-button-background); - color: var(--vscode-button-foreground); - border-color: var(--vscode-button-background); - } - .toolbar .spacer { flex: 1; } - .toolbar .info { font-size: 11px; opacity: .7; white-space: nowrap; } - .canvas-wrap { - flex: 1; - position: relative; - overflow: hidden; - } - canvas { - display: block; - width: 100%; - height: 100%; - cursor: crosshair; - } - .color-bar { - display: flex; - align-items: center; - gap: 6px; - padding: 4px 10px; - border-top: 1px solid var(--vscode-panel-border); - font-size: 11px; - flex-shrink: 0; - } - .color-swatch { - width: 14px; height: 14px; - border: 1px solid gray; - border-radius: 2px; - flex-shrink: 0; - } - .modal-overlay { - display: none; - position: fixed; - inset: 0; - background: rgba(0,0,0,.45); - z-index: 100; - align-items: center; - justify-content: center; - } - .modal-overlay.visible { display: flex; } - .modal { - background: var(--vscode-editorWidget-background); - border: 1px solid var(--vscode-panel-border); - border-radius: 8px; - padding: 18px 22px; - min-width: 340px; - box-shadow: 0 8px 32px rgba(0,0,0,.4); - } - .modal h3 { margin-bottom: 12px; font-size: 14px; } - .modal .row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; } - .modal label { width: 70px; text-align: right; font-size: 12px; opacity: .8; } - .modal input[type="text"], - .modal input[type="number"] { - flex: 1; - padding: 4px 8px; - border-radius: 3px; - border: 1px solid var(--vscode-input-border, transparent); - background: var(--vscode-input-background); - color: var(--vscode-input-foreground); - font-size: 13px; - outline: none; - } - .modal input:focus { border-color: var(--vscode-focusBorder); } - .modal .error { color: var(--vscode-errorForeground); font-size: 11px; margin-top: 4px; } - .modal .actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; } - .modal .actions button { - padding: 5px 16px; - border-radius: 3px; - border: 1px solid var(--vscode-button-secondaryBackground, rgba(128,128,128,.3)); - background: var(--vscode-button-secondaryBackground); - color: var(--vscode-button-secondaryForeground); - cursor: pointer; - font-size: 12px; - } - .modal .actions button.primary { - background: var(--vscode-button-background); - color: var(--vscode-button-foreground); - border-color: var(--vscode-button-background); - } - .empty { - flex: 1; - display: flex; - align-items: center; - justify-content: center; - opacity: .5; - } +/* 标注面板(共享层见 media/shared/tokens.css + controls.css) + 工具条/模态按钮用共享 .mini-btn / .icon-btn;本文件保留画布、色条与模态排版。 */ + +* { box-sizing: border-box; margin: 0; padding: 0; } + +body { + color: var(--text-primary); + background: var(--bg-page); + font-family: var(--font-ui); + font-size: var(--font-size-root); + overflow: hidden; + height: 100vh; + display: flex; + flex-direction: column; +} + +.toolbar { + border-bottom: var(--border-width) solid var(--border); + flex-shrink: 0; +} +.toolbar .spacer { flex: 1; } +.toolbar .info { color: var(--text-muted); font-size: var(--font-xs); white-space: nowrap; } + +.canvas-wrap { + flex: 1; + position: relative; + overflow: hidden; +} + +canvas { + display: block; + width: 100%; + height: 100%; + cursor: crosshair; +} + +.color-bar { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-xs) var(--space-md); + border-top: var(--border-width) solid var(--border); + color: var(--text-muted); + font-size: var(--font-xs); + flex-shrink: 0; +} +.color-swatch { + width: 14px; + height: 14px; + border: var(--border-width) solid var(--border); + border-radius: var(--radius-sm); + flex-shrink: 0; +} + +/* ── 模态(BBox 输入)────────────────────────────────────────────────── */ +.modal-overlay { + display: none; + position: fixed; + inset: 0; + background: var(--scrim); + z-index: 100; + align-items: center; + justify-content: center; +} +.modal-overlay.visible { display: flex; } + +.modal { + background: var(--bg-container-raised); + border: var(--border-width) solid var(--border); + border-radius: var(--radius-lg); + padding: var(--space-lg) 22px; + min-width: 340px; + box-shadow: var(--shadow-lg); +} +.modal h3 { margin-bottom: var(--space-sm); font-size: var(--font-lg); font-weight: var(--weight-bold); } +.modal .row { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-sm); } +.modal label { width: 70px; text-align: right; color: var(--text-muted); font-size: var(--font-sm); } +.modal input[type="text"], +.modal input[type="number"] { flex: 1; } +.modal .error { color: var(--err); font-size: var(--font-xs); margin-top: var(--space-xs); } +.modal .actions { display: flex; justify-content: flex-end; gap: var(--space-sm); margin-top: var(--space-lg); } + +.empty { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-muted); +} diff --git a/media/characterManager/characterManager.css b/media/characterManager/characterManager.css index 5556bd2..5323e71 100644 --- a/media/characterManager/characterManager.css +++ b/media/characterManager/characterManager.css @@ -1,52 +1,42 @@ :root { - --border: var(--vscode-panel-border, rgba(128,128,128,.28)); - --muted: var(--vscode-descriptionForeground, rgba(180,180,180,.75)); - --surface: var(--vscode-editorWidget-background, rgba(128,128,128,.06)); - --surface2: var(--vscode-sideBar-background, rgba(128,128,128,.05)); - --selected: var(--vscode-list-activeSelectionBackground, rgba(0,122,204,.28)); - --selected-fg: var(--vscode-list-activeSelectionForeground, inherit); - --hover: var(--vscode-list-hoverBackground, rgba(128,128,128,.12)); - --accent: var(--vscode-focusBorder, #007acc); - --danger: var(--vscode-errorForeground, #f48771); - --warning: var(--vscode-editorWarning-foreground, #cca700); - --info: var(--vscode-editorInfo-foreground, #75beff); + /* 面板内沿用短别名,全部指向共享 token(media/shared/tokens.css)—— + 颜色只有一个真源,这里的名字只是历史可读性写法。 + --border / --muted / --surface 直接来自共享层。 */ + --surface2: var(--bg-container-raised); + --selected: var(--selected-bg); + --hover: var(--surface-hover); + --accent: var(--border-strong); + --danger: var(--err); + --warning: var(--warn); + --info: var(--run); } * { box-sizing: border-box; } html, body { height: 100%; } body { margin: 0; - color: var(--vscode-editor-foreground); - background: var(--vscode-editor-background); - font-family: var(--vscode-font-family); - font-size: var(--vscode-font-size, 13px); + color: var(--text-primary); + background: var(--bg-page); + font-family: var(--font-ui); + font-size: var(--font-size-root); overflow: hidden; } -button, input, select, textarea { font: inherit; color: inherit; } -button { - border: 1px solid transparent; - border-radius: 4px; - background: var(--vscode-button-background); - color: var(--vscode-button-foreground); - padding: 5px 10px; - cursor: pointer; -} -button:hover { background: var(--vscode-button-hoverBackground); } -button.secondary { background: var(--vscode-button-secondaryBackground); color: var(--vscode-button-secondaryForeground); } -button.secondary:hover { background: var(--vscode-button-secondaryHoverBackground); } +/* 基础 button / input / select / textarea 视觉由共享层提供(media/shared/controls.css), + 这里只保留本面板的语义变体与图标按钮尺寸。 */ +button, input, select, textarea { font: inherit; } button.icon { padding: 4px 7px; min-width: 28px; } button.utility-button { width: 30px; height: 30px; border-color: var(--border); - background: var(--surface); - color: var(--vscode-foreground); + background: var(--bg-control); + color: var(--text-primary); padding: 0; - font-size: 15px; - box-shadow: 0 1px 2px rgba(0,0,0,.16); + font-size: var(--font-lg); + box-shadow: var(--shadow-sm); } button.utility-button:hover { border-color: color-mix(in srgb, var(--accent) 65%, var(--border)); - background: var(--hover); + background: var(--bg-control-hover); } button.action-button { display: inline-flex; @@ -56,85 +46,79 @@ button.action-button { min-height: 30px; border-color: var(--border); padding: 4px 10px; - font-weight: 600; + font-weight: var(--weight-medium); line-height: 1.2; white-space: nowrap; - box-shadow: 0 1px 2px rgba(0,0,0,.2); + box-shadow: var(--shadow-sm); } -button.action-button:hover { box-shadow: 0 2px 5px rgba(0,0,0,.24); } +button.action-button:hover { box-shadow: var(--shadow); } button.action-button:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; } -button.action-button.compact { min-height: 26px; padding: 3px 8px; font-size: 11px; } +button.action-button.compact { min-height: 26px; padding: 3px 8px; font-size: var(--font-xs); } button.action-add, button.action-save { border-color: color-mix(in srgb, var(--accent) 75%, var(--border)); - background: var(--vscode-button-background); - color: var(--vscode-button-foreground); + background: var(--btn-bg); + color: var(--btn-fg); } -button.action-add:hover, button.action-save:hover { background: var(--vscode-button-hoverBackground); } +button.action-add:hover, button.action-save:hover { background: var(--btn-bg-hover); } button.action-edit { border-color: color-mix(in srgb, var(--accent) 65%, var(--border)); - background: var(--vscode-button-secondaryBackground); - color: var(--vscode-button-secondaryForeground); + background: var(--btn-secondary-bg); + color: var(--btn-secondary-fg); } -button.action-edit:hover { background: var(--vscode-button-secondaryHoverBackground); } +button.action-edit:hover { background: var(--btn-secondary-bg-hover); } button.action-open { border-color: color-mix(in srgb, var(--info) 60%, var(--border)); background: color-mix(in srgb, var(--info) 9%, var(--surface)); - color: var(--vscode-foreground); + color: var(--text-primary); } button.action-open:hover { background: color-mix(in srgb, var(--info) 18%, var(--hover)); } button.action-cancel { border-color: var(--border); - background: var(--vscode-button-secondaryBackground); - color: var(--vscode-button-secondaryForeground); + background: var(--btn-secondary-bg); + color: var(--btn-secondary-fg); } -button.action-cancel:hover { background: var(--vscode-button-secondaryHoverBackground); } +button.action-cancel:hover { background: var(--btn-secondary-bg-hover); } button.action-delete { border-color: color-mix(in srgb, var(--danger) 70%, var(--border)); - background: var(--vscode-inputValidation-errorBackground, #5a1d1d); - color: var(--vscode-errorForeground, #fff); -} -button.action-delete:hover { background: color-mix(in srgb, var(--danger) 32%, var(--vscode-inputValidation-errorBackground, #5a1d1d)); } -input, select, textarea { - border: 1px solid var(--vscode-input-border, transparent); - border-radius: 3px; - background: var(--vscode-input-background); - color: var(--vscode-input-foreground); - padding: 5px 8px; - outline: none; + background: var(--danger-bg); + color: var(--btn-fg); +} +button.action-delete:hover { + background: color-mix(in srgb, var(--danger) 32%, var(--danger-bg)); } input:focus, select:focus, textarea:focus { border-color: var(--accent); } -input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholderForeground); } +input::placeholder, textarea::placeholder { color: var(--input-placeholder); } #app { height: 100%; display: flex; flex-direction: column; } .topbar { flex: 0 0 auto; border-bottom: 1px solid var(--border); - background: var(--vscode-titleBar-activeBackground, var(--vscode-editor-background)); + background: var(--bg-container-raised); } .title-row { min-height: 42px; display: flex; gap: 10px; align-items: center; padding: 7px 12px; } -.title { font-size: 15px; font-weight: 700; white-space: nowrap; } -#project { color: var(--muted); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.title { font-size: var(--font-lg); font-weight: var(--weight-bold); white-space: nowrap; } +#project { color: var(--muted); font-size: var(--font-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .spacer { flex: 1; } #globalSearch { width: min(360px, 35vw); } .tabs { display: flex; gap: 2px; padding: 0 10px; } .tab { border: none; border-bottom: 2px solid transparent; - border-radius: 0; - background: transparent; + border-radius: var(--radius-sm) var(--radius-sm) 0 0; + background: var(--bg-row); color: var(--muted); padding: 7px 11px 6px; } -.tab:hover { background: var(--hover); color: inherit; } -.tab.active { border-bottom-color: var(--accent); color: inherit; font-weight: 600; } +.tab:hover { background: var(--bg-row-hover); color: var(--text-primary); } +.tab.active { border-bottom-color: var(--accent); background: var(--bg-control); color: var(--text-primary); font-weight: var(--weight-medium); } .badge { display: inline-block; min-width: 18px; margin-left: 5px; - border-radius: 10px; + border-radius: var(--radius-pill); padding: 0 5px; - background: var(--vscode-badge-background); - color: var(--vscode-badge-foreground); - font-size: 10px; + background: var(--badge-bg); + color: var(--badge-fg); + font-size: var(--font-2xs); line-height: 17px; text-align: center; } @@ -147,9 +131,9 @@ input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholde border-bottom: 1px solid var(--border); background: var(--surface2); } -.metric { border: 1px solid var(--border); border-radius: 5px; background: var(--surface); padding: 6px 8px; } -.metric-value { font-size: 17px; font-weight: 700; } -.metric-label { color: var(--muted); font-size: 10px; margin-top: 1px; } +.metric { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); padding: 6px 8px; } +.metric-value { font-size: var(--font-xl); font-weight: var(--weight-bold); } +.metric-label { color: var(--muted); font-size: var(--font-2xs); margin-top: 1px; } .metric.error .metric-value { color: var(--danger); } .metric.warning .metric-value { color: var(--warning); } .content { flex: 1 1 auto; min-height: 0; position: relative; } @@ -172,14 +156,14 @@ input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholde .filter-check { grid-column: 1 / -1; color: var(--muted); - font-size: 11px; + font-size: var(--font-xs); display: flex; align-items: center; gap: 5px; } .filter-check input { width: auto; } -.list-head { display: flex; align-items: center; padding: 6px 9px; color: var(--muted); font-size: 11px; border-bottom: 1px solid var(--border); } -.scroll { overflow: auto; min-height: 0; scrollbar-color: var(--vscode-scrollbarSlider-background) transparent; } +.list-head { display: flex; align-items: center; padding: 6px 9px; color: var(--muted); font-size: var(--font-xs); border-bottom: 1px solid var(--border); } +.scroll { overflow: auto; min-height: 0; scrollbar-color: var(--scrollbar) transparent; } #characterList { flex: 1 1 auto; } .character-item { display: grid; @@ -187,7 +171,7 @@ input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholde gap: 8px; align-items: center; padding: 7px 9px; - border-bottom: 1px solid rgba(128,128,128,.1); + border-bottom: var(--border-width) solid var(--border); cursor: pointer; } .character-item:hover { background: var(--hover); } @@ -199,26 +183,26 @@ input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholde align-items: center; justify-content: center; border-radius: 50%; - font-weight: 700; + font-weight: var(--weight-bold); background: color-mix(in srgb, var(--accent) 22%, transparent); border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent); overflow: hidden; flex: 0 0 auto; } .avatar img { display: block; width: 100%; height: 100%; object-fit: contain; } -.avatar-large { width: 64px; height: 64px; font-size: 22px; } +.avatar-large { width: 64px; height: 64px; font-size: var(--font-xl); } .item-main { min-width: 0; } -.item-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } -.item-sub { color: var(--muted); font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } -.item-count { color: var(--muted); font-size: 10px; } +.item-name { font-weight: var(--weight-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.item-sub { color: var(--muted); font-size: var(--font-2xs); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.item-count { color: var(--muted); font-size: var(--font-2xs); } .issue-dot { display: inline-block; min-width: 16px; padding: 0 4px; margin-left: 4px; text-align: center; - border-radius: 8px; - color: #fff; + border-radius: var(--radius-md); + color: var(--on-accent); background: var(--warning); } .issue-dot.error { background: var(--danger); } @@ -235,18 +219,18 @@ input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholde } .character-identity { display: flex; align-items: flex-start; gap: 12px; min-width: 0; } .character-actions { display: flex; gap: 6px; flex-wrap: wrap; } -.character-title { font-size: 23px; font-weight: 700; } -.character-id { color: var(--muted); font-family: var(--vscode-editor-font-family); font-size: 11px; } +.character-title { font-size: var(--font-xl); font-weight: var(--weight-bold); } +.character-id { color: var(--muted); font-family: var(--font-mono); font-size: var(--font-xs); } .chips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; } .chip { display: inline-flex; align-items: center; gap: 4px; border: 1px solid var(--border); - border-radius: 12px; + border-radius: var(--radius-pill); background: var(--surface); padding: 2px 7px; - font-size: 11px; + font-size: var(--font-xs); } .chip.effect { cursor: pointer; padding-right: 5px; } .chip.effect:hover { border-color: var(--accent); } @@ -258,14 +242,14 @@ input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholde color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, var(--surface)); } -.effect-chip-name { font-weight: 600; } +.effect-chip-name { font-weight: var(--weight-medium); } .effect-chip-id, .effect-chip-count { border-left: 1px solid var(--border); padding-left: 5px; color: var(--muted); - font-family: var(--vscode-editor-font-family); - font-size: 9px; + font-family: var(--font-mono); + font-size: var(--font-2xs); } .chip.effect.negative .effect-chip-id, .chip.effect.negative .effect-chip-count { @@ -273,31 +257,31 @@ input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholde color: inherit; } .locales-inline { display: grid; grid-template-columns: repeat(auto-fit, minmax(145px, 1fr)); gap: 4px 10px; margin-top: 8px; } -.locale-name { display: flex; gap: 6px; min-width: 0; font-size: 11px; } +.locale-name { display: flex; gap: 6px; min-width: 0; font-size: var(--font-xs); } .locale-key { color: var(--muted); width: 48px; flex: 0 0 auto; } .locale-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.section-title { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; margin: 13px 0 7px; } +.section-title { display: flex; align-items: center; gap: 6px; font-size: var(--font-md); font-weight: var(--weight-bold); margin: 13px 0 7px; } .section-title > .action-button { margin-left: 3px; } -.skill-card { border: 1px solid var(--border); border-radius: 6px; background: var(--surface); margin-bottom: 8px; overflow: hidden; } +.skill-card { border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface); margin-bottom: 8px; overflow: hidden; } .skill-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--border); } -.skill-name { font-size: 14px; font-weight: 700; } -.skill-id { color: var(--muted); font-family: var(--vscode-editor-font-family); font-size: 10px; } +.skill-name { font-size: var(--font-lg); font-weight: var(--weight-bold); } +.skill-id { color: var(--muted); font-family: var(--font-mono); font-size: var(--font-2xs); } .clickable-id, .clickable-name { cursor: pointer; } .skill-meta { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px; } .skill-meta .action-button { align-self: center; } .skill-body { padding: 8px 10px 10px; } .description { line-height: 1.55; white-space: pre-wrap; } -.kv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 5px 12px; margin: 7px 0; font-size: 11px; } +.kv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 5px 12px; margin: 7px 0; font-size: var(--font-xs); } .kv-key { color: var(--muted); margin-right: 5px; } .effect-line { margin-top: 7px; } -.line-label { color: var(--muted); font-size: 11px; margin-bottom: 4px; } +.line-label { color: var(--muted); font-size: var(--font-xs); margin-bottom: 4px; } .trigger-mode-wrap { display: flex; align-items: flex-start; gap: 0; margin-top: 6px; border: 1px solid; - border-radius: 6px; + border-radius: var(--radius-md); overflow: hidden; } .trigger-mode-wrap.mode-any { @@ -333,8 +317,8 @@ input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholde .trigger-mode-wrap.mode-any .trigger-mode-icon svg { stroke: var(--warning); } .trigger-mode-wrap.mode-all .trigger-mode-icon svg { stroke: var(--info); } .trigger-mode-label { - font-size: 9px; - font-weight: 700; + font-size: var(--font-2xs); + font-weight: var(--weight-bold); letter-spacing: .8px; text-transform: uppercase; margin-top: 3px; @@ -357,19 +341,19 @@ input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholde border-radius: 0 4px 4px 0; } .enhancement-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; min-height: 30px; } -.enhancement-name { flex: 1 1 auto; min-width: 0; font-weight: 700; } +.enhancement-name { flex: 1 1 auto; min-width: 0; font-weight: var(--weight-bold); } .enhancement-actions { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 6px; } .enhancement-actions .action-button { min-width: 72px; } .enhancement-trigger { margin-top: 4px; line-height: 1.4; } -.pulse { color: var(--info); font-size: 10px; margin-left: 5px; } +.pulse { color: var(--info); font-size: var(--font-2xs); margin-left: 5px; } .add-enhancement-action { margin-top: 8px; } .empty { padding: 36px 20px; text-align: center; color: var(--muted); line-height: 1.7; } .table-wrap { width: 100%; overflow: auto; } -table { border-collapse: collapse; width: 100%; font-size: 11px; } +table { border-collapse: collapse; width: 100%; font-size: var(--font-xs); } th, td { border: 1px solid var(--border); padding: 6px 8px; text-align: left; vertical-align: top; } -th { position: sticky; top: 0; z-index: 2; background: var(--vscode-editorWidget-background); white-space: nowrap; } -td.sticky, th.sticky { position: sticky; left: 0; z-index: 3; background: var(--vscode-editor-background); min-width: 175px; } -th.sticky { z-index: 4; background: var(--vscode-editorWidget-background); } +th { position: sticky; top: 0; z-index: 2; background: var(--bg-container); white-space: nowrap; } +td.sticky, th.sticky { position: sticky; left: 0; z-index: 3; background: var(--bg-page); min-width: 175px; } +th.sticky { z-index: 4; background: var(--bg-container); } .missing-cell { background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger); } .effect-toolbar, .issues-toolbar, .locale-toolbar { flex: 0 0 auto; @@ -389,19 +373,19 @@ th.sticky { z-index: 4; background: var(--vscode-editorWidget-background); } padding: 8px 7px; } .effect-card:hover { background: var(--hover); } -.effect-name { font-size: 13px; font-weight: 700; } -.effect-id { font-family: var(--vscode-editor-font-family); font-weight: 700; word-break: break-all; } +.effect-name { font-size: var(--font-md); font-weight: var(--weight-bold); } +.effect-id { font-family: var(--font-mono); font-weight: var(--weight-bold); word-break: break-all; } .effect-desc { line-height: 1.4; } -.usage-list { margin-top: 5px; color: var(--muted); font-size: 10px; } +.usage-list { margin-top: 5px; color: var(--muted); font-size: var(--font-2xs); } .usage { cursor: pointer; margin: 2px 0; } .usage:hover { color: inherit; text-decoration: underline; } -.severity { font-weight: 700; text-transform: uppercase; font-size: 10px; } +.severity { font-weight: var(--weight-bold); text-transform: uppercase; font-size: var(--font-2xs); } .severity.error { color: var(--danger); } .severity.warning { color: var(--warning); } .severity.info { color: var(--info); } .issue-row { display: grid; grid-template-columns: 62px 145px minmax(0, 1fr) auto; gap: 9px; align-items: start; padding: 7px 6px; border-bottom: 1px solid var(--border); } .issue-row:hover { background: var(--hover); } -.issue-code { color: var(--muted); font-family: var(--vscode-editor-font-family); font-size: 10px; } +.issue-code { color: var(--muted); font-family: var(--font-mono); font-size: var(--font-2xs); } #loading, #fatal { position: absolute; inset: 0; @@ -409,7 +393,7 @@ th.sticky { z-index: 4; background: var(--vscode-editorWidget-background); } display: none; align-items: center; justify-content: center; - background: color-mix(in srgb, var(--vscode-editor-background) 92%, transparent); + background: color-mix(in srgb, var(--bg-page) 92%, transparent); padding: 24px; text-align: center; } @@ -423,7 +407,7 @@ th.sticky { z-index: 4; background: var(--vscode-editorWidget-background); } align-items: center; justify-content: center; padding: 24px; - background: rgba(0,0,0,.58); + background: var(--scrim); } .modal-backdrop.show { display: flex; } .modal { @@ -432,27 +416,27 @@ th.sticky { z-index: 4; background: var(--vscode-editorWidget-background); } display: flex; flex-direction: column; border: 1px solid var(--border); - border-radius: 7px; - background: var(--vscode-editorWidget-background); - box-shadow: 0 12px 36px rgba(0,0,0,.42); + border-radius: var(--radius-lg); + background: var(--bg-container); + box-shadow: var(--shadow-lg); } .modal-head, .modal-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border); } .modal-actions { justify-content: flex-end; border-bottom: none; border-top: 1px solid var(--border); } -.modal-title { font-size: 15px; font-weight: 700; } +.modal-title { font-size: var(--font-lg); font-weight: var(--weight-bold); } .modal-body { overflow: auto; padding: 12px; } .modal-error { padding: 0 12px; } .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px 12px; } .form-field { min-width: 0; } .form-field.wide { grid-column: 1 / -1; } -.form-field label { display: block; margin-bottom: 3px; color: var(--muted); font-size: 11px; } +.form-field label { display: block; margin-bottom: 3px; color: var(--muted); font-size: var(--font-xs); } .form-field input, .form-field select, .form-field textarea { width: 100%; } .form-field textarea { min-height: 76px; resize: vertical; } -.form-field textarea.json { min-height: 125px; font-family: var(--vscode-editor-font-family); font-size: 11px; } +.form-field textarea.json { min-height: 125px; font-family: var(--font-mono); font-size: var(--font-xs); } .locked-notice { grid-column: 1 / -1; border: 1px solid color-mix(in srgb, var(--info) 55%, var(--border)); border-left: 3px solid var(--info); - border-radius: 4px; + border-radius: var(--radius-sm); background: color-mix(in srgb, var(--info) 8%, transparent); padding: 8px 10px; line-height: 1.45; @@ -461,8 +445,8 @@ th.sticky { z-index: 4; background: var(--vscode-editorWidget-background); } min-height: 30px; border: 1px solid var(--border); border-left: 3px solid var(--muted); - border-radius: 3px; - background: color-mix(in srgb, var(--vscode-input-background) 55%, transparent); + border-radius: var(--radius-sm); + background: color-mix(in srgb, var(--input-bg) 55%, transparent); padding: 6px 8px; color: var(--muted); cursor: default; @@ -470,14 +454,14 @@ th.sticky { z-index: 4; background: var(--vscode-editorWidget-background); } } .readonly-value.multiline { min-height: 76px; line-height: 1.5; white-space: pre-wrap; } .effect-editor { display: grid; grid-template-columns: minmax(230px, .8fr) minmax(300px, 1.2fr); gap: 10px; } -.effect-select { min-height: 210px; font-family: var(--vscode-editor-font-family); font-size: 11px; } -.effect-editor-hint { color: var(--muted); font-size: 10px; margin-top: 4px; } +.effect-select { min-height: 210px; font-family: var(--font-mono); font-size: var(--font-xs); } +.effect-editor-hint { color: var(--muted); font-size: var(--font-2xs); margin-top: 4px; } .effect-params { display: flex; flex-direction: column; gap: 6px; max-height: 310px; overflow: auto; } -.effect-param-row { border: 1px solid var(--border); border-radius: 5px; padding: 6px 7px; background: var(--surface); } -.effect-param-title { font-family: var(--vscode-editor-font-family); font-size: 11px; font-weight: 700; margin-bottom: 5px; } -.effect-param-desc { color: var(--muted); font-size: 10px; margin-bottom: 5px; } +.effect-param-row { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px 7px; background: var(--surface); } +.effect-param-title { font-family: var(--font-mono); font-size: var(--font-xs); font-weight: var(--weight-bold); margin-bottom: 5px; } +.effect-param-desc { color: var(--muted); font-size: var(--font-2xs); margin-bottom: 5px; } .effect-param-grid { display: grid; grid-template-columns: repeat(4, minmax(70px, 1fr)); gap: 5px; } -.effect-param-grid label { color: var(--muted); font-size: 9px; } +.effect-param-grid label { color: var(--muted); font-size: var(--font-2xs); } .effect-param-grid input, .effect-param-grid select { width: 100%; margin-top: 2px; } .form-check { display: flex; align-items: center; gap: 6px; min-height: 30px; } .form-check input { width: auto; } diff --git a/media/characterManager/index.html b/media/characterManager/index.html index 5e81662..c4eb05f 100644 --- a/media/characterManager/index.html +++ b/media/characterManager/index.html @@ -5,7 +5,9 @@