twskin 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,23 @@ All notable changes to this package are documented here. This project follows
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.6.3] - 2026-07-29
9
+
10
+ ### Fixed
11
+
12
+ - Corrected the semantic foreground for TRAE's inverted primary actions. Settings,
13
+ Automation, Marketplace and their dialogs now use a high-contrast foreground
14
+ independently from the brand-color foreground in every official theme.
15
+ - Removed the fixed pale strip behind the Templates tabs and the Automation Run
16
+ History filter bar, while preserving the hierarchy of their interactive controls.
17
+ - Made injected runtime payloads read their version from the packaged manifest,
18
+ preventing a current runtime from being mistaken for an older injection.
19
+
20
+ ### For contributors
21
+
22
+ - Added full-catalog regression coverage for primary-action foreground contrast
23
+ across every official theme and all TRAE token namespaces.
24
+
8
25
  ## [0.6.2] - 2026-07-29
9
26
 
10
27
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "twskin",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "An unofficial community theme manager and CLI for TRAE Work on macOS.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,7 +16,14 @@ import { spawnSync } from "node:child_process";
16
16
  import { fileURLToPath } from "node:url";
17
17
 
18
18
  const ROOT = path.dirname(fileURLToPath(import.meta.url));
19
- const VERSION = "0.5.10";
19
+ const VERSION = (() => {
20
+ if (process.env.TWSKIN_RUNTIME_VERSION) return process.env.TWSKIN_RUNTIME_VERSION;
21
+ try {
22
+ const manifest = JSON.parse(fs.readFileSync(path.join(ROOT, "manifest.json"), "utf8"));
23
+ if (typeof manifest.packageVersion === "string" && manifest.packageVersion) return manifest.packageVersion;
24
+ } catch {}
25
+ return "development";
26
+ })();
20
27
  const DATA_DIR = process.env.TWSKIN_DATA_DIR || path.join(os.homedir(), ".trae-work-skin");
21
28
 
22
29
  function parseArgs(argv) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "0.6.2",
3
+ "packageVersion": "0.6.3",
4
4
  "themesBundled": false,
5
5
  "files": [
6
6
  {
@@ -10,8 +10,8 @@
10
10
  },
11
11
  {
12
12
  "path": "injector.mjs",
13
- "size": 31309,
14
- "sha256": "7560f2353b03dd52a60fc6b7a87825b03e621e651a3f8c780c2ab03f91f88934"
13
+ "size": 31648,
14
+ "sha256": "7b0854c2b8b14323df1d5d469188ef3a0e290c7484aefd58bb3b29d19c0c056a"
15
15
  },
16
16
  {
17
17
  "path": "restore.sh",
@@ -20,8 +20,8 @@
20
20
  },
21
21
  {
22
22
  "path": "skin.js",
23
- "size": 62024,
24
- "sha256": "4cc53fd2534ba09b15ffe8260f3684430c2fd2477cfdb254f4bd5d31a7eb184b"
23
+ "size": 62070,
24
+ "sha256": "c2c259652046286048ee0a298ab08210ae3dd8dd226e6410ee888610b41cd96c"
25
25
  },
26
26
  {
27
27
  "path": "start.sh",
@@ -30,8 +30,8 @@
30
30
  },
31
31
  {
32
32
  "path": "styles/base.css",
33
- "size": 35586,
34
- "sha256": "a8bb84a963b8353372bb226c05b81bcaebe982ff18a45355a241f4d24b47e8ba"
33
+ "size": 36601,
34
+ "sha256": "4fb182ba011d330b9ff668d12a25c10eec07ff1c20cb924dbb2598a44a1b8d49"
35
35
  },
36
36
  {
37
37
  "path": "styles/manager.css",
@@ -40,8 +40,8 @@
40
40
  },
41
41
  {
42
42
  "path": "token-map.mjs",
43
- "size": 24446,
44
- "sha256": "7c79c75e7ba634febc9817c55eef2e314a9e92362b6f190ea903e363a65557df"
43
+ "size": 24840,
44
+ "sha256": "11ccf9f72410ac6b936d1fcd58d1087b933cef9697137a6a92a51593dcf6e0cb"
45
45
  }
46
46
  ]
47
47
  }
package/runtime/skin.js CHANGED
@@ -416,6 +416,7 @@
416
416
  setVar("--trae-skin-success", state.success);
417
417
  setVar("--trae-skin-input", surface.input);
418
418
  setVar("--trae-skin-menu", surface.menu);
419
+ setVar("--trae-skin-card", surface.card);
419
420
  setVar("--trae-skin-card-hover", surface.cardHover);
420
421
  setVar("--trae-skin-border-subtle", border.subtle);
421
422
  setVar("--trae-skin-border-default", border.default);
@@ -311,6 +311,23 @@ body.trae-skin-v2 [role="menuitem"][data-state="checked"] {
311
311
  background: var(--trae-skin-popover-selected) !important;
312
312
  }
313
313
 
314
+ /* Templates 的 CSS module 固定用纯白 tab strip;让容器回归透明,
315
+ 仅由搜索框与选中态承担控件层级。只匹配含 tabRow 的栏目导航,
316
+ 避免影响其他同前缀的内部 tab 容器。 */
317
+ body.trae-skin-v2 :is([class^="tabsBar-"], [class*=" tabsBar-"]):has(> :is([class^="tabRow-"], [class*=" tabRow-"])) {
318
+ background: transparent !important;
319
+ }
320
+
321
+ /* Automation Run History 的筛选条在宿主中强制占用基础背景,形成一整块
322
+ 不透明色带。条本身应融入页面,仅让可操作的筛选控件使用 input 表面。 */
323
+ body.trae-skin-v2 :is([class^="filterBar-"], [class*=" filterBar-"]):has(> :is([class^="statusSelect-"], [class*=" statusSelect-"])) {
324
+ background: transparent !important;
325
+ }
326
+ body.trae-skin-v2 :is([class^="filterBar-"], [class*=" filterBar-"]):has(> :is([class^="statusSelect-"], [class*=" statusSelect-"]))
327
+ :is([role="combobox"], [class^="trigger-"], [class*=" trigger-"]) {
328
+ background: var(--trae-skin-input) !important;
329
+ }
330
+
314
331
  /* Account card:Trae Work 使用独立 CSS module,不走通用 popover。 */
315
332
  body.trae-skin-v2 [class*="account-module__card___"],
316
333
  body.trae-skin-v2 [class*="account-module__subMenuInner___"] {
@@ -179,6 +179,11 @@
179
179
  function buildVarMap(tokens, opts) {
180
180
  const r = deriveRoles(tokens, opts);
181
181
  const { accent, surface, text, icons, border, state } = r;
182
+ // TRAE 的原生语义并不对称:`*-onbrand` 配对 `bg-bg-brand`,
183
+ // 而 Marketplace / Automation / Settings 的主操作使用
184
+ // `bg-bg-invert` + `*-onaccent`。不能把二者都绑定到 accent,
185
+ // 否则浅色主题的深色 invert 表面会拿到同色文字。
186
+ const onInvert = pickOnColor(surface.invert);
182
187
  const out = {};
183
188
 
184
189
  // bg 语义(后缀共享:--bg-bg-* / --vscode-icube--bg-bg-* / --ras-bg-bg-*)
@@ -221,7 +226,8 @@
221
226
  case "disabled": return text.disabled;
222
227
  case "brand": case "brand-sub": case "brand-design": return accent.base;
223
228
  case "brand-hover": case "brand-hover-sub": case "brand-hover-design": return accent.hover;
224
- case "onaccent": case "onbrand": return accent.onAccent;
229
+ case "onaccent": return onInvert;
230
+ case "onbrand": return accent.onAccent;
225
231
  case "preformat-foreground": return text.secondary;
226
232
  default: return undefined;
227
233
  }
@@ -234,7 +240,8 @@
234
240
  case "disabled": return icons.disabled;
235
241
  case "brand": case "brand-sub": case "brand-design": return accent.base;
236
242
  case "brand-hover": case "brand-hover-sub": case "brand-hover-design": return accent.hover;
237
- case "onaccent": case "onbrand": return accent.onAccent;
243
+ case "onaccent": return onInvert;
244
+ case "onbrand": return accent.onAccent;
238
245
  case "white": return "#ffffff";
239
246
  default: return undefined;
240
247
  }