dsh-theme-palette 1.5.2 → 1.6.0
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 +42 -0
- package/README-es.md +2 -0
- package/README-hi.md +2 -0
- package/README-pt.md +2 -0
- package/README-zh.md +3 -1
- package/README.md +3 -1
- package/client.js +96 -98
- package/docs/DESIGN.md +14 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -13,6 +13,48 @@
|
|
|
13
13
|
复核宿主源码发现它带 `includePrerelease`,结论相反。现在这条判断固化进脚本,不再靠手算
|
|
14
14
|
- 该改动只影响本地发版工具,**不进 npm 包**(`files` 不含 `tools/`),故不升版本号
|
|
15
15
|
|
|
16
|
+
### 1.6.0
|
|
17
|
+
视觉与可访问性整改(依据 2026-10-22 第三方 UI 视觉验收审计,60/100):
|
|
18
|
+
|
|
19
|
+
- **A2 配置块重做**:改用 `.dsh-tp-field` 容器(与普通行同节奏),导出/导入各占一行,
|
|
20
|
+
反馈文案就地显示(复制→复制按钮旁,导入→导入按钮旁),导出框加 `text-overflow:ellipsis`
|
|
21
|
+
- **A3 复制不再谎报**:`await navigator.clipboard.writeText()`,失败或无 API 时显示
|
|
22
|
+
「复制失败,请手选后 Ctrl+C」,不再无条件报成功
|
|
23
|
+
- **A4 布局从视口断点改容器驱动**:卡片 `repeat(auto-fit,minmax(196px,1fr))`、色块 `minmax(86px,1fr)`、
|
|
24
|
+
行与分段控件 `flex-wrap`;日语长标签改短(右栏「サイドバー / キャンバス」、滚动条「無彩 / 追従 / 強調」)。
|
|
25
|
+
实测 4 语 × 内容宽 564/336/216:**越界元素 0**(改前日语 216px 溢出 61px)
|
|
26
|
+
- **A5 语言属性**:`<section lang>` 跟随手选语言,`auto` 时回落宿主 `documentElement.lang`
|
|
27
|
+
- **A6 分段控件有名字**:`role="radiogroup"` + `aria-labelledby` 指向行标题,选项改
|
|
28
|
+
`role="radio" aria-checked`(8 组 22 个按钮)
|
|
29
|
+
- **A7 反馈可播报**:复制/导入/自愈状态挂 `role="status" aria-live="polite"`,错误用 `alert`;
|
|
30
|
+
导入框补 `aria-label`
|
|
31
|
+
- **A8 自定义面板层级**:面板底改 `bg-layer-1`(按钮不再与面板同底 1.00:1)、说明文字提到
|
|
32
|
+
`label-secondary` 12px;色值从只读 `<code>` 改为**可输入 hex**(回车/失焦生效,非法值忽略)
|
|
33
|
+
- **A9 缩略图跟随侧栏档位**:`cardColors()` 接收 `sidebarMode`,不再写死默认档
|
|
34
|
+
- **A11** 黑白配色下「滚动条」「开关」置灰禁用(点了也不会有变化)
|
|
35
|
+
- **A12** 卡片与分段按钮 `:focus-visible{outline-offset:2px}`,焦点环不再与选中边框贴死
|
|
36
|
+
- **A13** 加 `prefers-reduced-motion` 降级
|
|
37
|
+
- **A14** `docs/DESIGN.md` 补「当前标定值」表(旧推演内容保留,注明以 `client.js` 为准)
|
|
38
|
+
- **A15** 删掉 4 语共 36 条从未渲染的文案键与未被调用的 `swatches()`
|
|
39
|
+
- **A10 证据链**:README 首图换成当前版本(5 张卡)的**静态渲染**,按真机内容宽 564 px 出图
|
|
40
|
+
(浅色 / 深色 / 自定义面板三张,`--scale 2` 即 1240 px 宽),并在五语 README 里注明「静态渲染」;
|
|
41
|
+
`screenshots.json` 同步为这三张
|
|
42
|
+
- 工具:`tools/preview-settings.mjs` 新增 `--width`(默认按真机 564px 内容宽)与 `--adv`(默认折叠),
|
|
43
|
+
token 跟随 `--palette`;新增 `tools/measure-preview.mjs`(量越界/行高/关键计算色,非 0 越界退出 1)
|
|
44
|
+
|
|
45
|
+
### 1.5.3
|
|
46
|
+
修:选中「自定义」后滚动条不跟随取色。
|
|
47
|
+
|
|
48
|
+
- **根因**:`scrollbarTokens()` 收到的是 `SCHEMES` 里的**占位** scheme 对象
|
|
49
|
+
(`accentHue` 恒为 60),而真正按三色派生出的参数只在 `rampsFor()` 内部解引用。
|
|
50
|
+
于是画布/强调色都对,唯独滚动条永远停在暖橙。
|
|
51
|
+
- **修法**:`buildTokens()` 开头统一解引用一次(`params = scheme.custom ? customScheme(readCustom()) : scheme`),
|
|
52
|
+
之后所有读 `scheme.*` 的地方改用 `params`;`scrollbarTokens(ramps, params, mode)` 也改传解析后的对象。
|
|
53
|
+
- **防复发**:新增 `tools/check-custom.mjs` —— 断言三种强调色必须产出三种滚动条颜色,
|
|
54
|
+
且三组自选色的正文/次文/三级对比度仍在限内(现在输出
|
|
55
|
+
`#2f6fd0→#bfd6f9 #a9683e→#f2cbb3 #4f7a42→#c2ddbb`)。
|
|
56
|
+
- 顺带:`tools/preview-settings.mjs` 支持 `PREVIEW_ACCENT`,可预览任意强调色的自定义面板。
|
|
57
|
+
|
|
16
58
|
### 1.5.2
|
|
17
59
|
设置页交互重排(用户反馈:自定义不该埋在「更多选项」里、取色看不到即时效果):
|
|
18
60
|
|
package/README-es.md
CHANGED
|
@@ -6,6 +6,8 @@ Paleta de tema para DeepSeek Harness (web y escritorio): **4 paletas × claro/os
|
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
9
|
+
*Render estático con el ancho real del panel (564 px de contenido).*
|
|
10
|
+
|
|
9
11
|
## Compatibility
|
|
10
12
|
|
|
11
13
|
| Superficie | Estado |
|
package/README-hi.md
CHANGED
package/README-pt.md
CHANGED
|
@@ -6,6 +6,8 @@ Paleta de tema para o DeepSeek Harness (web e desktop): **4 paletas × claro/esc
|
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
9
|
+
*Render estático na largura real do painel (564 px de conteúdo).*
|
|
10
|
+
|
|
9
11
|
## Compatibility
|
|
10
12
|
|
|
11
13
|
| Superfície | Estado |
|
package/README-zh.md
CHANGED
package/README.md
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
Theme palette for DeepSeek Harness (web & desktop): **4 palettes × light/dark**, two independent axes.
|
|
6
6
|
|
|
7
|
-

|
|
8
|
+
|
|
9
|
+
*Static render of the settings page at the real panel width (564 px content).*
|
|
8
10
|
|
|
9
11
|
## Compatibility
|
|
10
12
|
|
package/client.js
CHANGED
|
@@ -27,7 +27,7 @@ window.__ModuleLoader__.load({
|
|
|
27
27
|
const React = require('react')
|
|
28
28
|
const h = React.createElement
|
|
29
29
|
|
|
30
|
-
const PLUGIN_VERSION = '1.
|
|
30
|
+
const PLUGIN_VERSION = '1.6.0'
|
|
31
31
|
const STORE_KEY = 'dsh-theme-palette.v1'
|
|
32
32
|
const OVERRIDE_SOURCE = 'dsh-theme-palette'
|
|
33
33
|
|
|
@@ -703,9 +703,12 @@ window.__ModuleLoader__.load({
|
|
|
703
703
|
|
|
704
704
|
function buildTokens(scheme, sidebarMode, textMode, rightbarMode, scrollMode, controlMode, mdMode, hcMode) {
|
|
705
705
|
const hc = hcMode === true
|
|
706
|
-
|
|
706
|
+
// 自定义配色必须先解引用:ramps 内部会派生参数,但 accent / scroll / control
|
|
707
|
+
// 这些直接读 params.accentHue、params.hue 的地方若拿到占位值,就会"不跟取色"
|
|
708
|
+
const params = scheme && scheme.custom === true ? customScheme(readCustom()) : scheme
|
|
709
|
+
const ramps = rampsFor(params, textMode || DEFAULT_TEXT, hc)
|
|
707
710
|
const pairs = {}
|
|
708
|
-
if (!
|
|
711
|
+
if (!params.tinted) {
|
|
709
712
|
// 黑白:只输出「被求解改动过」的那几步 + 派生链接,不整条覆盖(保持宿主原貌)
|
|
710
713
|
for (const step of ['400', '600', '700', '1000']) {
|
|
711
714
|
pairs['--dsw-static-neutral-bluish-' + step] = { light: ramps.bluish[step], dark: ramps.bluish[step] }
|
|
@@ -719,7 +722,7 @@ window.__ModuleLoader__.load({
|
|
|
719
722
|
pairs['--dsw-alias-button-primary-fill'] = { light: monoBtn, dark: ramps.bluish['1000'] }
|
|
720
723
|
}
|
|
721
724
|
// 其它配色:整条色阶 + 字面量别名覆盖。
|
|
722
|
-
if (
|
|
725
|
+
if (params.tinted) {
|
|
723
726
|
for (const [family, table] of Object.entries(ramps)) {
|
|
724
727
|
for (const [step, value] of Object.entries(table)) {
|
|
725
728
|
pairs['--dsw-static-' + (family === 'bluish' ? 'neutral-bluish-' : family + '-') + step] = {
|
|
@@ -731,13 +734,13 @@ window.__ModuleLoader__.load({
|
|
|
731
734
|
const aliases = aliasOverrides(ramps, hc)
|
|
732
735
|
for (const [name, pair] of Object.entries(aliases)) pairs[name] = pair
|
|
733
736
|
}
|
|
734
|
-
const sidebar = sidebarTokens(ramps, sidebarMode,
|
|
737
|
+
const sidebar = sidebarTokens(ramps, sidebarMode, params.tinted)
|
|
735
738
|
for (const [name, pair] of Object.entries(sidebar)) pairs[name] = pair
|
|
736
739
|
// 右栏底色只给一个间接层:同左栏时直接引用左栏 token,跟随画布时引用画布 token。
|
|
737
740
|
// 主按钮:浅色下宿主把 button-primary-fill 指到 state-error-primary(红),
|
|
738
741
|
// 于是页面上有「红主按钮 + 强调色」两个主色。改成强调色,并压暗到按钮文字 ≥4.5。
|
|
739
742
|
// 黑白配色在上面已经单独设过,这里跳过(它要按「更浅」档的画布兜底)。
|
|
740
|
-
if (
|
|
743
|
+
if (params.tinted) {
|
|
741
744
|
pairs['--dsw-alias-button-primary-fill'] = {
|
|
742
745
|
light: darkenUntil(ramps.deepseek['500'], ramps.bluish['00'], 4.5),
|
|
743
746
|
dark: ramps.deepseek['400'],
|
|
@@ -756,7 +759,7 @@ window.__ModuleLoader__.load({
|
|
|
756
759
|
: 'var(--dsw-specific-sidebar-fill)'
|
|
757
760
|
pairs['--dshtp-rightbar-fill'] = { light: rightbarFill, dark: rightbarFill }
|
|
758
761
|
// Markdown 强调色:标题 = 正文色混 40% 强调色;加粗 = 混 20%(比标题弱一档)
|
|
759
|
-
if (
|
|
762
|
+
if (params.tinted) {
|
|
760
763
|
if (mdMode === 'off') {
|
|
761
764
|
const inherit = { light: 'inherit', dark: 'inherit' }
|
|
762
765
|
pairs['--dshtp-md-heading'] = inherit
|
|
@@ -790,7 +793,7 @@ window.__ModuleLoader__.load({
|
|
|
790
793
|
light: mixHex(ramps.deepseek['500'], ramps.bluish['50'], 0.05),
|
|
791
794
|
dark: mixHex(ramps.deepseek['400'], ramps.bluish['900'], 0.07),
|
|
792
795
|
}
|
|
793
|
-
const scroll = scrollbarTokens(ramps,
|
|
796
|
+
const scroll = scrollbarTokens(ramps, params, scrollMode)
|
|
794
797
|
for (const [name, pair] of Object.entries(scroll)) pairs[name] = pair
|
|
795
798
|
// 开关/勾选/单选的共用支点:brand-primary 本来是近黑/近白,改成强调色。
|
|
796
799
|
if (controlMode === 'accent') {
|
|
@@ -798,22 +801,16 @@ window.__ModuleLoader__.load({
|
|
|
798
801
|
}
|
|
799
802
|
// 黑白配色的浅色画布本身就是纯白,「更浅」无处可提 —— 改成把会话区压一档浅灰,
|
|
800
803
|
// 侧栏保持纯白,同样得到区块层次(这是唯一需要动画布的情形)。
|
|
801
|
-
if (!
|
|
804
|
+
if (!params.tinted && sidebarMode === 'light') {
|
|
802
805
|
pairs['--dsw-static-neutral-bluish-00'] = { light: '#fafafa', dark: BASE.bluish['00'] }
|
|
803
806
|
}
|
|
804
807
|
return pairs
|
|
805
808
|
}
|
|
806
809
|
|
|
807
|
-
|
|
808
|
-
function swatches(scheme, textMode) {
|
|
809
|
-
if (!scheme.tinted) return ['#ffffff', '#e5e5e5', '#0f1115']
|
|
810
|
-
const r = rampsFor(scheme, textMode || DEFAULT_TEXT)
|
|
811
|
-
return [r.bluish['00'], r.bluish['100'], r.deepseek['500']]
|
|
812
|
-
}
|
|
813
|
-
|
|
810
|
+
|
|
814
811
|
|
|
815
812
|
/** 卡片缩略图用的一小组颜色(画布/侧栏/文字/强调),按当前强度档取。 */
|
|
816
|
-
function cardColors(scheme, textMode) {
|
|
813
|
+
function cardColors(scheme, textMode, sidebarMode) {
|
|
817
814
|
const r = rampsFor(scheme, textMode || DEFAULT_TEXT)
|
|
818
815
|
if (!r) {
|
|
819
816
|
return {
|
|
@@ -821,7 +818,7 @@ window.__ModuleLoader__.load({
|
|
|
821
818
|
dark: { canvas: '#151517', side: '#1b1b1c', text: '#f9fafb', accent: '#7aaaff' },
|
|
822
819
|
}
|
|
823
820
|
}
|
|
824
|
-
const side = sidebarTokens(r, DEFAULT_SIDEBAR, scheme.tinted)
|
|
821
|
+
const side = sidebarTokens(r, sidebarMode || DEFAULT_SIDEBAR, scheme.tinted)
|
|
825
822
|
return {
|
|
826
823
|
light: {
|
|
827
824
|
canvas: r.bluish['00'],
|
|
@@ -865,10 +862,10 @@ window.__ModuleLoader__.load({
|
|
|
865
862
|
.dsh-tp-head h2{margin:0;font-size:18px;font-weight:600;letter-spacing:.2px}
|
|
866
863
|
.dsh-tp-badge{margin-left:auto;font:11px/1.7 ui-monospace,Consolas,monospace;color:var(--dsw-alias-label-tertiary);border:.5px solid var(--dsw-alias-border-l4);border-radius:999px;padding:0 8px}
|
|
867
864
|
.dsh-tp-sub{margin:-6px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}
|
|
868
|
-
.dsh-tp-grid{display:grid;grid-template-columns:repeat(
|
|
869
|
-
|
|
870
|
-
.dsh-tp-card{position:relative;display:flex;flex-direction:column;gap:8px;text-align:left;font:inherit;cursor:pointer;padding:9px;border-radius:14px;border:.5px solid var(--dsw-alias-border-l4);background:transparent;transition:background .12s ease,border-color .12s ease}
|
|
865
|
+
.dsh-tp-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(196px,1fr));gap:10px}
|
|
866
|
+
.dsh-tp-card{position:relative;display:flex;flex-direction:column;gap:8px;text-align:left;font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;padding:9px;border-radius:14px;border:.5px solid var(--dsw-alias-border-l4);background:transparent;transition:background .12s ease,border-color .12s ease}
|
|
871
867
|
.dsh-tp-card:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
868
|
+
.dsh-tp-card:focus-visible{outline-offset:2px}
|
|
872
869
|
.dsh-tp-card.is-on{background:var(--dshtp-card-picked,var(--dsw-alias-bg-module-platform));border-color:var(--t-accent-l)}
|
|
873
870
|
body[data-ds-dark-theme] .dsh-tp-card.is-on{border-color:var(--t-accent-d)}
|
|
874
871
|
.dsh-tp-thumb{display:flex;height:56px;border-radius:9px;overflow:hidden;border:.5px solid rgba(128,128,128,.28)}
|
|
@@ -882,20 +879,21 @@ body[data-ds-dark-theme] .dsh-tp-thumb-main b{background:var(--t-text-d)}
|
|
|
882
879
|
.dsh-tp-thumb-main b:nth-of-type(3){width:44%;background:var(--t-accent-l);opacity:.9}
|
|
883
880
|
body[data-ds-dark-theme] .dsh-tp-thumb-main b:nth-of-type(3){background:var(--t-accent-d)}
|
|
884
881
|
.dsh-tp-card-meta{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
|
|
885
|
-
.dsh-tp-card-name{font-size:
|
|
886
|
-
.dsh-tp-card-desc{font-size:
|
|
882
|
+
.dsh-tp-card-name{font-size:14px;font-weight:500}
|
|
883
|
+
.dsh-tp-card-desc{font-size:12px;color:var(--dsw-alias-label-tertiary)}
|
|
887
884
|
.dsh-tp-check{position:absolute;top:7px;right:7px;width:16px;height:16px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:10px;line-height:1;background:var(--t-accent-l);color:var(--t-canvas-l);opacity:0;transition:opacity .12s ease}
|
|
888
885
|
body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--t-canvas-d)}
|
|
889
886
|
.dsh-tp-card.is-on .dsh-tp-check{opacity:1}
|
|
890
|
-
.dsh-tp-row{display:flex;align-items:center;gap:12px;padding:11px 0;border-top:.5px solid var(--dsw-alias-border-l2)}
|
|
887
|
+
.dsh-tp-row{display:flex;align-items:center;gap:12px;padding:11px 0;border-top:.5px solid var(--dsw-alias-border-l2);flex-wrap:wrap}
|
|
891
888
|
.dsh-tp-row-label{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
|
|
892
889
|
.dsh-tp-row-label b{font-size:13.5px;font-weight:500}
|
|
893
890
|
.dsh-tp-row-label span{font-size:11.5px;color:var(--dsw-alias-label-tertiary);line-height:16px}
|
|
894
|
-
.dsh-tp-seg{display:inline-flex;gap:2px;padding:2px;border-radius:10px;background:var(--dsw-alias-interactive-bg-hover);flex:none}
|
|
891
|
+
.dsh-tp-seg{display:inline-flex;flex-wrap:wrap;gap:2px;padding:2px;border-radius:10px;background:var(--dsw-alias-interactive-bg-hover);flex:none;max-width:100%}
|
|
895
892
|
.dsh-tp-seg button{font:inherit;font-size:12.5px;line-height:20px;cursor:pointer;border:0;border-radius:8px;padding:5px 12px;background:transparent;color:var(--dsw-alias-label-secondary);white-space:nowrap;transition:background .12s,color .12s}
|
|
896
893
|
.dsh-tp-seg button:hover{color:var(--dsw-alias-label-primary)}
|
|
897
894
|
.dsh-tp-seg button.is-on{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);box-shadow:0 1px 2px rgba(0,0,0,.10)}
|
|
898
|
-
|
|
895
|
+
.dsh-tp-seg button:focus-visible{outline-offset:2px}
|
|
896
|
+
.dsh-tp-seg button[disabled]{opacity:.45;cursor:default}
|
|
899
897
|
.dsh-tp-more{display:inline-flex;align-items:center;gap:6px;font:inherit;font-size:12.5px;color:var(--dsw-alias-label-tertiary);background:0 0;border:0;padding:6px 0 2px;cursor:pointer;align-self:flex-start;transition:color .12s}
|
|
900
898
|
.dsh-tp-more:hover{color:var(--dsw-alias-label-primary)}
|
|
901
899
|
.dsh-tp-adv{display:flex;flex-direction:column}
|
|
@@ -903,21 +901,27 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
903
901
|
.dsh-tp-input::placeholder{color:var(--dsw-alias-label-tertiary)}
|
|
904
902
|
.dsh-tp-mini{font:inherit;font-size:12.5px;line-height:20px;padding:5px 12px;border-radius:8px;border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);cursor:pointer}
|
|
905
903
|
.dsh-tp-mini:hover{background:var(--dsw-alias-bg-layer-1)}
|
|
906
|
-
.dsh-tp-custom{display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:14px;border:.5px solid var(--dsw-alias-border-
|
|
904
|
+
.dsh-tp-custom{display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:14px;border:.5px solid var(--dsw-alias-border-l3);background:var(--dsw-alias-bg-layer-1)}
|
|
907
905
|
.dsh-tp-custom-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
|
|
908
906
|
.dsh-tp-custom-head b{font-size:13.5px;font-weight:500}
|
|
909
|
-
.dsh-tp-swatches{display:grid;grid-template-columns:repeat(
|
|
910
|
-
@media (max-width:520px){.dsh-tp-swatches{grid-template-columns:1fr}}
|
|
907
|
+
.dsh-tp-swatches{display:grid;grid-template-columns:repeat(auto-fit,minmax(86px,1fr));gap:10px}
|
|
911
908
|
.dsh-tp-swatch{display:flex;flex-direction:column;gap:6px;cursor:pointer}
|
|
912
909
|
.dsh-tp-color{width:100%;height:44px;padding:0;border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;background:transparent;cursor:pointer}
|
|
913
910
|
.dsh-tp-color::-webkit-color-swatch-wrapper{padding:3px}
|
|
914
911
|
.dsh-tp-color::-webkit-color-swatch{border:none;border-radius:8px}
|
|
915
912
|
.dsh-tp-swatch-name{font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
916
913
|
.dsh-tp-hex{font:11.5px/1 ui-monospace,Consolas,monospace;color:var(--dsw-alias-label-tertiary)}
|
|
917
|
-
.dsh-tp-
|
|
914
|
+
.dsh-tp-hexinput{width:100%;box-sizing:border-box;font:11.5px/16px ui-monospace,Consolas,monospace;padding:3px 6px;border-radius:6px;border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary)}
|
|
915
|
+
.dsh-tp-hexinput:focus-visible{outline-offset:1px}
|
|
916
|
+
.dsh-tp-custom-hint{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}
|
|
918
917
|
.dsh-tp-note{font-size:11.5px;color:var(--dsw-alias-label-tertiary)}
|
|
919
918
|
.dsh-tp-status{margin:0;font-size:11.5px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
920
919
|
.dsh-tp-status.is-bad{color:var(--dsw-alias-state-error-primary)}
|
|
920
|
+
.dsh-tp-field{display:flex;flex-direction:column;gap:8px;padding:11px 0;border-top:.5px solid var(--dsw-alias-border-l2)}
|
|
921
|
+
.dsh-tp-field-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
|
|
922
|
+
.dsh-tp-field-title{font-size:13.5px;font-weight:500}
|
|
923
|
+
.dsh-tp-input{text-overflow:ellipsis}
|
|
924
|
+
@media (prefers-reduced-motion:reduce){.dsh-tp-card,.dsh-tp-seg button,.dsh-tp-more,.dsh-tp-check,.dsh-tp-mini{transition:none}}
|
|
921
925
|
`
|
|
922
926
|
|
|
923
927
|
function installRightbarStyle() {
|
|
@@ -1169,14 +1173,10 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1169
1173
|
nav: '主题色',
|
|
1170
1174
|
hint: '配色与明暗模式独立;切换后立即生效并保存在 localStorage。',
|
|
1171
1175
|
md: 'Markdown 强调',
|
|
1172
|
-
mdHint: '标题与加粗用「正文色混强调色」,比正文更有色;关掉则与正文同色。',
|
|
1173
1176
|
control: '开关 / 勾选',
|
|
1174
|
-
controlHint: '宿主的开关、复选框、单选都压在近黑/近白上;开启后改用强调色。',
|
|
1175
1177
|
scroll: '滚动条',
|
|
1176
|
-
scrollHint: '默认中性灰;「跟随」上配色色相,「强调」用强调色。明暗关系不变。',
|
|
1177
1178
|
scrollHintMono: '当前是黑白配色,没有色相可跟随,滚动条保持中性灰。',
|
|
1178
1179
|
rightbar: '右侧栏底色',
|
|
1179
|
-
rightbarHint: '右栏本来没有自己的背景,露的是会话区画布色。',
|
|
1180
1180
|
advanced: '更多选项',
|
|
1181
1181
|
textSub: '正文与强调的着色程度',
|
|
1182
1182
|
sidebarSub: '相对会话区的层次',
|
|
@@ -1185,16 +1185,11 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1185
1185
|
scrollSub: '滚动条与滑轨的色相',
|
|
1186
1186
|
controlSub: '开关与复选框是否跟强调色',
|
|
1187
1187
|
langSub: '自动跟随宿主界面语言',
|
|
1188
|
-
surface: '面板表面',
|
|
1189
|
-
surfaceHint: '决定侧栏与右栏相对会话区是「浮起」还是「凹陷」。',
|
|
1190
|
-
ok: '✓ 配色已生效',
|
|
1191
1188
|
bad: '⚠ 部分 token 未生效(宿主可能改名),请查看控制台',
|
|
1192
1189
|
healed: '配色层被宿主丢过一次,已自动恢复 ',
|
|
1193
1190
|
healedSuffix: ' 次',
|
|
1194
1191
|
text: '强度',
|
|
1195
|
-
textHint: '让正文/次级文字带配色色味;三档都满足 AA。',
|
|
1196
1192
|
sidebar: '左侧栏底色',
|
|
1197
|
-
sidebarHint: '让侧栏比会话区更浅(或更深),做出区块层次。',
|
|
1198
1193
|
lang: '语言',
|
|
1199
1194
|
hc: '高对比',
|
|
1200
1195
|
custom: '自定义配色',
|
|
@@ -1205,6 +1200,7 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1205
1200
|
copy: '复制',
|
|
1206
1201
|
applyImport: '导入',
|
|
1207
1202
|
copied: '已复制',
|
|
1203
|
+
copyFail: '复制失败,请手选后 Ctrl+C',
|
|
1208
1204
|
importOk: '已导入',
|
|
1209
1205
|
importBad: '短码无效,已忽略',
|
|
1210
1206
|
hcSub: '把文字下限抬到 AAA(正文 ≥15、次文 ≥9、三级 ≥7)',
|
|
@@ -1213,14 +1209,10 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1213
1209
|
nav: '主題色',
|
|
1214
1210
|
hint: '配色與明暗模式獨立;切換後立即生效並存在 localStorage。',
|
|
1215
1211
|
md: 'Markdown 強調',
|
|
1216
|
-
mdHint: '標題與粗體用「本文色混強調色」,比本文更有色;關掉則與本文同色。',
|
|
1217
1212
|
control: '開關 / 勾選',
|
|
1218
|
-
controlHint: '宿主開關、核取方塊、單選都用近黑/近白;開啟後改用強調色。',
|
|
1219
1213
|
scroll: '捲軸',
|
|
1220
|
-
scrollHint: '預設中性灰;「跟隨」上配色色相,「強調」用強調色。明暗關係不變。',
|
|
1221
1214
|
scrollHintMono: '目前是黑白配色,沒有色相可跟隨,捲軸保持中性灰。',
|
|
1222
1215
|
rightbar: '右側欄底色',
|
|
1223
|
-
rightbarHint: '右欄本來沒有自己的背景,露的是會話區畫布色。',
|
|
1224
1216
|
advanced: '更多選項',
|
|
1225
1217
|
textSub: '本文與強調的著色程度',
|
|
1226
1218
|
sidebarSub: '相對會話區的層次',
|
|
@@ -1229,16 +1221,11 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1229
1221
|
scrollSub: '捲軸與軌道的色相',
|
|
1230
1222
|
controlSub: '開關與核取方塊是否跟強調色',
|
|
1231
1223
|
langSub: '自動跟隨宿主介面語言',
|
|
1232
|
-
surface: '面板表面',
|
|
1233
|
-
surfaceHint: '決定側欄與右欄相對會話區是「浮起」還是「凹陷」。',
|
|
1234
|
-
ok: '✓ 配色已生效',
|
|
1235
1224
|
bad: '⚠ 部分 token 未生效(宿主可能改名),請看主控台',
|
|
1236
1225
|
healed: '配色層被宿主丟棄過一次,已自動恢復 ',
|
|
1237
1226
|
healedSuffix: ' 次',
|
|
1238
1227
|
text: '強度',
|
|
1239
|
-
textHint: '讓本文/次級文字帶配色色味;三檔都符合 AA。',
|
|
1240
1228
|
sidebar: '左側欄底色',
|
|
1241
|
-
sidebarHint: '讓側欄比會話區更淺(或更深),做出區塊層次。',
|
|
1242
1229
|
lang: '語言',
|
|
1243
1230
|
hc: '高對比',
|
|
1244
1231
|
custom: '自訂配色',
|
|
@@ -1249,6 +1236,7 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1249
1236
|
copy: '複製',
|
|
1250
1237
|
applyImport: '匯入',
|
|
1251
1238
|
copied: '已複製',
|
|
1239
|
+
copyFail: '複製失敗,請手選後 Ctrl+C',
|
|
1252
1240
|
importOk: '已匯入',
|
|
1253
1241
|
importBad: '短碼無效,已忽略',
|
|
1254
1242
|
hcSub: '把文字下限抬到 AAA(正文 ≥15、次文 ≥9、三級 ≥7)',
|
|
@@ -1257,14 +1245,10 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1257
1245
|
nav: 'Color theme',
|
|
1258
1246
|
hint: 'Independent of light/dark mode. Applies immediately and is saved to localStorage.',
|
|
1259
1247
|
md: 'Markdown emphasis',
|
|
1260
|
-
mdHint: 'Headings and bold mix the accent into body colour; off keeps them identical to body text.',
|
|
1261
1248
|
control: 'Switches / checks',
|
|
1262
|
-
controlHint: 'Switches, checkboxes and radios use near-black/white in the host. Turn this on to use the accent colour.',
|
|
1263
1249
|
scroll: 'Scrollbars',
|
|
1264
|
-
scrollHint: 'Neutral grey by default. Tint follows the palette hue; Accent uses the accent colour. Lightness is unchanged.',
|
|
1265
1250
|
scrollHintMono: 'Monochrome has no hue to follow; scrollbars stay neutral.',
|
|
1266
1251
|
rightbar: 'Right panel surface',
|
|
1267
|
-
rightbarHint: 'The right panel has no fill of its own; it shows the canvas.',
|
|
1268
1252
|
advanced: 'More options',
|
|
1269
1253
|
textSub: 'How strongly text follows the palette',
|
|
1270
1254
|
sidebarSub: 'Layer relative to the conversation',
|
|
@@ -1273,16 +1257,11 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1273
1257
|
scrollSub: 'Hue of the scrollbar',
|
|
1274
1258
|
controlSub: 'Switches and checkboxes',
|
|
1275
1259
|
langSub: 'Follow the host interface language',
|
|
1276
|
-
surface: 'Panel surfaces',
|
|
1277
|
-
surfaceHint: 'Whether the sidebars sit above or below the conversation area.',
|
|
1278
|
-
ok: '✓ Palette applied',
|
|
1279
1260
|
bad: '⚠ Some tokens did not apply (host may have renamed them); check the console',
|
|
1280
1261
|
healed: 'Palette layer was dropped by the host; restored ',
|
|
1281
1262
|
healedSuffix: 'x',
|
|
1282
1263
|
text: 'Strength',
|
|
1283
|
-
textHint: 'Tints body and secondary text toward the palette; all three levels meet AA.',
|
|
1284
1264
|
sidebar: 'Sidebar surface',
|
|
1285
|
-
sidebarHint: 'Makes the sidebar lighter (or deeper) than the conversation area.',
|
|
1286
1265
|
lang: 'Language',
|
|
1287
1266
|
hc: 'High contrast',
|
|
1288
1267
|
custom: 'Custom palette',
|
|
@@ -1293,6 +1272,7 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1293
1272
|
copy: 'Copy',
|
|
1294
1273
|
applyImport: 'Import',
|
|
1295
1274
|
copied: 'Copied',
|
|
1275
|
+
copyFail: 'Copy failed — select the code and press Ctrl+C',
|
|
1296
1276
|
importOk: 'Imported',
|
|
1297
1277
|
importBad: 'Invalid code, ignored',
|
|
1298
1278
|
hcSub: 'Raises text floors to AAA (body ≥15, secondary ≥9, tertiary ≥7)',
|
|
@@ -1301,14 +1281,10 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1301
1281
|
nav: 'カラーテーマ',
|
|
1302
1282
|
hint: 'ライト/ダークとは独立です。変更は即時反映され、localStorage に保存されます。',
|
|
1303
1283
|
md: 'Markdown の強調',
|
|
1304
|
-
mdHint: '見出しと太字にアクセント色を混ぜます。オフにすると本文と同じ色になります。',
|
|
1305
1284
|
control: 'スイッチ / チェック',
|
|
1306
|
-
controlHint: 'ホストのスイッチ・チェックボックスはほぼ白黒です。オンにするとアクセント色になります。',
|
|
1307
1285
|
scroll: 'スクロールバー',
|
|
1308
|
-
scrollHint: '既定はニュートラルグレー。「追従」でテーマの色相、「アクセント」でアクセント色になります。',
|
|
1309
1286
|
scrollHintMono: 'モノクロには色相がないため、スクロールバーはグレーのままです。',
|
|
1310
1287
|
rightbar: '右パネルの背景',
|
|
1311
|
-
rightbarHint: '右パネルは独自の背景を持たず、キャンバス色が見えています。',
|
|
1312
1288
|
advanced: 'その他のオプション',
|
|
1313
1289
|
textSub: '本文と強調の色づき具合',
|
|
1314
1290
|
sidebarSub: '会話エリアとの段差',
|
|
@@ -1317,16 +1293,11 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1317
1293
|
scrollSub: 'スクロールバーの色相',
|
|
1318
1294
|
controlSub: 'スイッチとチェックの色',
|
|
1319
1295
|
langSub: 'ホストの表示言語に合わせます',
|
|
1320
|
-
surface: 'パネル表面',
|
|
1321
|
-
surfaceHint: 'サイドバーが会話エリアより浮くか沈むかを決めます。',
|
|
1322
|
-
ok: '✓ 配色を適用しました',
|
|
1323
1296
|
bad: '⚠ 一部の token が適用されていません(ホスト側で改名された可能性)。コンソールを確認してください',
|
|
1324
1297
|
healed: '配色レイヤーがホストに破棄されたため、自動で復元しました(',
|
|
1325
1298
|
healedSuffix: ' 回)',
|
|
1326
1299
|
text: '強さ',
|
|
1327
|
-
textHint: '本文と副次テキストをテーマ色に寄せます。3 段階とも AA を満たします。',
|
|
1328
1300
|
sidebar: '左サイドバーの背景',
|
|
1329
|
-
sidebarHint: 'サイドバーを会話エリアより明るく(または暗く)して段差を作ります。',
|
|
1330
1301
|
lang: '言語',
|
|
1331
1302
|
hc: 'ハイコントラスト',
|
|
1332
1303
|
custom: 'カスタム配色',
|
|
@@ -1337,6 +1308,7 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1337
1308
|
copy: 'コピー',
|
|
1338
1309
|
applyImport: '読み込み',
|
|
1339
1310
|
copied: 'コピーしました',
|
|
1311
|
+
copyFail: 'コピーできません。選択して Ctrl+C してください',
|
|
1340
1312
|
importOk: '読み込みました',
|
|
1341
1313
|
importBad: '無効なコードです',
|
|
1342
1314
|
hcSub: '本文の下限を AAA に引き上げます(本文 ≥15、副次 ≥9、三次 ≥7)',
|
|
@@ -1389,8 +1361,8 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1389
1361
|
desc: { mono: '色なし · 既定', warm: 'クリーム + ブラウン', indigo: 'クールホワイト + ブルー', moss: 'グレーグリーン', custom: '3 色から派生' },
|
|
1390
1362
|
text: { neutral: '控えめ', tinted: '標準', deep: '強め' },
|
|
1391
1363
|
sidebar: { light: '明るく', match: '同じ', deep: '暗く' },
|
|
1392
|
-
rightbar: { sidebar: '
|
|
1393
|
-
scroll: { neutral: '
|
|
1364
|
+
rightbar: { sidebar: 'サイドバー', canvas: 'キャンバス' },
|
|
1365
|
+
scroll: { neutral: '無彩', tinted: '追従', accent: '強調' },
|
|
1394
1366
|
control: { accent: 'アクセント', mono: 'モノクロ' },
|
|
1395
1367
|
md: { on: '色づけ', off: '本文と同じ' },
|
|
1396
1368
|
lang: { auto: '自動' },
|
|
@@ -1412,32 +1384,42 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1412
1384
|
const health = React.useSyncExternalStore(props.subscribeHealth, props.getHealth)
|
|
1413
1385
|
const [importText, setImportText] = React.useState('')
|
|
1414
1386
|
const [importState, setImportState] = React.useState(null)
|
|
1387
|
+
const [copyState, setCopyState] = React.useState(null)
|
|
1415
1388
|
const [advanced, setAdvanced] = React.useState(false)
|
|
1416
1389
|
const locale = React.useSyncExternalStore(props.subscribeLocale, props.getLocale)
|
|
1417
1390
|
const langPref = React.useSyncExternalStore(props.subscribeLocale, props.getLangPref)
|
|
1391
|
+
const langAttr = langPref !== 'auto'
|
|
1392
|
+
? langPref
|
|
1393
|
+
: ((typeof document !== 'undefined' && document.documentElement && document.documentElement.lang) || 'zh-CN')
|
|
1418
1394
|
const txt = TEXT[locale] || TEXT['zh-CN']
|
|
1419
1395
|
const lb = LABELS[locale] || LABELS['zh-CN']
|
|
1420
1396
|
|
|
1421
|
-
|
|
1397
|
+
// A6:读屏需要知道"这是哪个设置的选项组";单选用 radio 语义更准
|
|
1398
|
+
const seg = (modes, value, onPick, labels, labelId, disabled) => h(
|
|
1422
1399
|
'div',
|
|
1423
|
-
{ className: 'dsh-tp-seg', role: '
|
|
1400
|
+
{ className: 'dsh-tp-seg', role: 'radiogroup', 'aria-labelledby': labelId, 'aria-disabled': disabled ? 'true' : undefined },
|
|
1424
1401
|
modes.map((mode) => h(
|
|
1425
1402
|
'button',
|
|
1426
1403
|
{
|
|
1427
1404
|
key: mode.id,
|
|
1428
1405
|
type: 'button',
|
|
1406
|
+
role: 'radio',
|
|
1429
1407
|
className: mode.id === value ? 'is-on' : undefined,
|
|
1430
|
-
'aria-
|
|
1431
|
-
|
|
1408
|
+
'aria-checked': mode.id === value,
|
|
1409
|
+
'aria-disabled': disabled ? 'true' : undefined,
|
|
1410
|
+
disabled: disabled === true,
|
|
1411
|
+
onClick: () => { if (!disabled) onPick(mode.id) },
|
|
1432
1412
|
},
|
|
1433
1413
|
(labels && labels[mode.id]) || mode.label,
|
|
1434
1414
|
)),
|
|
1435
1415
|
)
|
|
1436
1416
|
|
|
1437
|
-
const
|
|
1417
|
+
const rowId = (key) => 'dsh-tp-row-' + key
|
|
1418
|
+
const row = (key, titleText, subText, control) => h(
|
|
1438
1419
|
'div',
|
|
1439
1420
|
{ className: 'dsh-tp-row' },
|
|
1440
|
-
h('div', { className: 'dsh-tp-row-label'
|
|
1421
|
+
h('div', { className: 'dsh-tp-row-label', id: rowId(key) + '-desc' },
|
|
1422
|
+
h('b', { id: rowId(key) }, titleText), h('span', null, subText)),
|
|
1441
1423
|
control,
|
|
1442
1424
|
)
|
|
1443
1425
|
|
|
@@ -1465,13 +1447,21 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1465
1447
|
'aria-label': (lb.custom && lb.custom[field]) || field,
|
|
1466
1448
|
}),
|
|
1467
1449
|
h('span', { className: 'dsh-tp-swatch-name' }, (lb.custom && lb.custom[field]) || field),
|
|
1468
|
-
h('
|
|
1450
|
+
h('input', {
|
|
1451
|
+
key: customColors[field],
|
|
1452
|
+
className: 'dsh-tp-hexinput',
|
|
1453
|
+
defaultValue: customColors[field],
|
|
1454
|
+
spellCheck: false,
|
|
1455
|
+
'aria-label': ((lb.custom && lb.custom[field]) || field) + ' HEX',
|
|
1456
|
+
onBlur: (e) => props.setCustomColor(field, e.target.value.trim()),
|
|
1457
|
+
onKeyDown: (e) => { if (e.key === 'Enter') props.setCustomColor(field, e.target.value.trim()) },
|
|
1458
|
+
})))),
|
|
1469
1459
|
h('p', { className: 'dsh-tp-custom-hint' }, txt.customHint),
|
|
1470
1460
|
)
|
|
1471
1461
|
|
|
1472
1462
|
const card = (scheme) => {
|
|
1473
1463
|
const picked = scheme.id === current
|
|
1474
|
-
const c = cardColors(scheme, textMode)
|
|
1464
|
+
const c = cardColors(scheme, textMode, sidebarMode)
|
|
1475
1465
|
return h(
|
|
1476
1466
|
'button',
|
|
1477
1467
|
{
|
|
@@ -1499,16 +1489,16 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1499
1489
|
|
|
1500
1490
|
return h(
|
|
1501
1491
|
'section',
|
|
1502
|
-
{ className: 'dsh-tp' },
|
|
1492
|
+
{ className: 'dsh-tp', lang: langAttr },
|
|
1503
1493
|
h('div', { className: 'dsh-tp-head' },
|
|
1504
1494
|
h('h2', null, txt.nav),
|
|
1505
1495
|
h('span', { className: 'dsh-tp-badge' }, 'v' + PLUGIN_VERSION)),
|
|
1506
1496
|
h('p', { className: 'dsh-tp-sub' }, txt.hint),
|
|
1507
1497
|
h('div', { className: 'dsh-tp-grid' }, SCHEMES.map(card)),
|
|
1508
1498
|
customPanel,
|
|
1509
|
-
row(txt.text, txt.textSub, seg(TEXT_MODES, textMode, props.setTextMode, lb.text)),
|
|
1510
|
-
row(txt.sidebar, txt.sidebarSub, seg(SIDEBAR_MODES, sidebarMode, props.setSidebarMode, lb.sidebar)),
|
|
1511
|
-
row(txt.rightbar, txt.rightbarSub, seg(RIGHTBAR_MODES, rightbarMode, props.setRightbarMode, lb.rightbar)),
|
|
1499
|
+
row('text', txt.text, txt.textSub, seg(TEXT_MODES, textMode, props.setTextMode, lb.text, rowId('text'))),
|
|
1500
|
+
row('sidebar', txt.sidebar, txt.sidebarSub, seg(SIDEBAR_MODES, sidebarMode, props.setSidebarMode, lb.sidebar, rowId('sidebar'))),
|
|
1501
|
+
row('rightbar', txt.rightbar, txt.rightbarSub, seg(RIGHTBAR_MODES, rightbarMode, props.setRightbarMode, lb.rightbar, rowId('rightbar'))),
|
|
1512
1502
|
health && !health.ok && h('p', { className: 'dsh-tp-status is-bad' }, txt.bad),
|
|
1513
1503
|
health && health.ok && health.reapplies > 0 && h(
|
|
1514
1504
|
'p',
|
|
@@ -1524,35 +1514,43 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1524
1514
|
advanced && h(
|
|
1525
1515
|
'div',
|
|
1526
1516
|
{ className: 'dsh-tp-adv' },
|
|
1527
|
-
row(txt.lang, txt.langSub, seg(LANG_OPTIONS, langPref, props.setLangPref, lb.lang)),
|
|
1517
|
+
row('lang', txt.lang, txt.langSub, seg(LANG_OPTIONS, langPref, props.setLangPref, lb.lang, rowId('lang'))),
|
|
1528
1518
|
h(
|
|
1529
1519
|
'div',
|
|
1530
|
-
{
|
|
1531
|
-
h('div', {
|
|
1532
|
-
h('div', {
|
|
1520
|
+
{ className: 'dsh-tp-field' },
|
|
1521
|
+
h('div', { className: 'dsh-tp-field-title', id: rowId('config') }, txt.config),
|
|
1522
|
+
h('div', { className: 'dsh-tp-field-row' },
|
|
1533
1523
|
h('input', {
|
|
1534
1524
|
className: 'dsh-tp-input',
|
|
1535
1525
|
readOnly: true,
|
|
1536
1526
|
value: props.getConfigCode(),
|
|
1527
|
+
title: props.getConfigCode(),
|
|
1537
1528
|
onFocus: (e) => { try { e.target.select() } catch (err) { /* 忽略 */ } },
|
|
1538
|
-
'aria-label': txt.config,
|
|
1529
|
+
'aria-label': txt.config + ' — ' + txt.copy,
|
|
1539
1530
|
}),
|
|
1540
1531
|
h('button', {
|
|
1541
1532
|
type: 'button',
|
|
1542
1533
|
className: 'dsh-tp-mini',
|
|
1543
|
-
onClick: () => {
|
|
1534
|
+
onClick: async () => {
|
|
1544
1535
|
const code = props.getConfigCode()
|
|
1545
1536
|
try {
|
|
1546
|
-
if (navigator.clipboard
|
|
1547
|
-
|
|
1548
|
-
|
|
1537
|
+
if (!navigator.clipboard || typeof navigator.clipboard.writeText !== 'function') throw new Error('no clipboard api')
|
|
1538
|
+
await navigator.clipboard.writeText(code)
|
|
1539
|
+
setCopyState('copied')
|
|
1540
|
+
} catch (err) {
|
|
1541
|
+
// 剪贴板可能被拒(无安全上下文/权限);不能谎报成功
|
|
1542
|
+
setCopyState('fail')
|
|
1543
|
+
}
|
|
1549
1544
|
},
|
|
1550
|
-
}, txt.copy)
|
|
1551
|
-
|
|
1545
|
+
}, txt.copy),
|
|
1546
|
+
copyState && h('span', { className: 'dsh-tp-note', role: 'status', 'aria-live': 'polite' },
|
|
1547
|
+
copyState === 'copied' ? txt.copied : txt.copyFail)),
|
|
1548
|
+
h('div', { className: 'dsh-tp-field-row' },
|
|
1552
1549
|
h('input', {
|
|
1553
1550
|
className: 'dsh-tp-input',
|
|
1554
1551
|
placeholder: 'dshs1.…',
|
|
1555
1552
|
value: importText,
|
|
1553
|
+
'aria-label': txt.applyImport,
|
|
1556
1554
|
onChange: (e) => { setImportText(e.target.value); setImportState(null) },
|
|
1557
1555
|
}),
|
|
1558
1556
|
h('button', {
|
|
@@ -1560,14 +1558,14 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
|
|
|
1560
1558
|
className: 'dsh-tp-mini',
|
|
1561
1559
|
onClick: () => setImportState(props.applyConfigCode(importText) ? 'ok' : 'bad'),
|
|
1562
1560
|
}, txt.applyImport),
|
|
1563
|
-
importState && h('span', { className: 'dsh-tp-note' },
|
|
1564
|
-
importState === 'ok' ? txt.importOk :
|
|
1565
|
-
h('p', {
|
|
1561
|
+
importState && h('span', { className: 'dsh-tp-note', role: importState === 'bad' ? 'alert' : 'status', 'aria-live': 'polite' },
|
|
1562
|
+
importState === 'ok' ? txt.importOk : txt.importBad)),
|
|
1563
|
+
h('p', { className: 'dsh-tp-custom-hint' }, txt.configHint),
|
|
1566
1564
|
),
|
|
1567
|
-
row(txt.md, txt.mdSub, seg(MD_MODES, mdMode, props.setMdMode, lb.md)),
|
|
1568
|
-
row(txt.hc, txt.hcSub, seg(HC_MODES, hcMode, props.setHcMode, lb.hc)),
|
|
1569
|
-
row(txt.scroll, current === 'mono' ? txt.scrollHintMono : txt.scrollSub, seg(SCROLL_MODES, scrollMode, props.setScrollMode, lb.scroll)),
|
|
1570
|
-
row(txt.control, txt.controlSub, seg(CONTROL_MODES, controlMode, props.setControlMode, lb.control)),
|
|
1565
|
+
row('md', txt.md, txt.mdSub, seg(MD_MODES, mdMode, props.setMdMode, lb.md, rowId('md'))),
|
|
1566
|
+
row('hc', txt.hc, txt.hcSub, seg(HC_MODES, hcMode, props.setHcMode, lb.hc, rowId('hc'))),
|
|
1567
|
+
row('scroll', txt.scroll, current === 'mono' ? txt.scrollHintMono : txt.scrollSub, seg(SCROLL_MODES, scrollMode, props.setScrollMode, lb.scroll, rowId('scroll'), current === 'mono')),
|
|
1568
|
+
row('control', txt.control, txt.controlSub, seg(CONTROL_MODES, controlMode, props.setControlMode, lb.control, rowId('control'), current === 'mono')),
|
|
1571
1569
|
),
|
|
1572
1570
|
)
|
|
1573
1571
|
}
|
package/docs/DESIGN.md
CHANGED
|
@@ -42,6 +42,20 @@
|
|
|
42
42
|
旧写法把 `-0.020×0.6` 夹成 `-0.004`,深色导轨与画布只剩 ΔE 0.49 —— 边界直接消失,
|
|
43
43
|
而同一档在浅色侧是 2.10。现在两侧都是 1.9–2.1,同一个档位在明暗两模式下强度一致。
|
|
44
44
|
|
|
45
|
+
## 当前标定值(真源:`client.js`)
|
|
46
|
+
|
|
47
|
+
> 下面各节的推演过程保留原样(它们是当时的推理轨迹),但**具体数值以本表为准**。
|
|
48
|
+
> 2026-10-22 视觉审计发现旧表格仍写着 1.8 / 2.6 与「中性 / 跟随 / 浓一些」,与实现已不一致。
|
|
49
|
+
|
|
50
|
+
| 档位(UI 文案) | id | textScale | paperScale | textLift |
|
|
51
|
+
|---|---|---|---|---|
|
|
52
|
+
| 静 | `neutral` | 1 | 1 | 0 |
|
|
53
|
+
| **标准(默认)** | `tinted` | 3.0 | 2.4 | +0.055 |
|
|
54
|
+
| 浓 | `deep` | 4.6 | 3.6 | +0.085 |
|
|
55
|
+
|
|
56
|
+
高对比档(`HC_MODES`,默认关)把文字下限整体抬到正文 ≥15 / 次文 ≥9 / 三级 ≥7 / 链接 ≥7,
|
|
57
|
+
并把求解器位移上限从 0.13 放宽到 0.30(低档位下 4.6 → 7 需要 ΔL≈0.2,原上限够不着)。
|
|
58
|
+
|
|
45
59
|
## 文字着色
|
|
46
60
|
|
|
47
61
|
正文原来只给 0.004 的色度(近中性),视觉上就是「黑字 / 白字」。现在有第三行「文字着色」,
|