agentcss 0.11.9 → 0.11.11
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/01-tokens/page.css +71 -0
- package/02-primitives/badge/README.md +14 -0
- package/02-primitives/button/demo.html +5 -15
- package/02-primitives/card/README.md +1 -1
- package/02-primitives/card/demo.html +3 -13
- package/02-primitives/choice/demo.html +1 -0
- package/02-primitives/combobox/README.md +15 -0
- package/02-primitives/combobox/demo.html +38 -0
- package/02-primitives/date-range/README.md +11 -0
- package/02-primitives/date-range/demo.html +36 -0
- package/02-primitives/input/demo.html +5 -16
- package/02-primitives/popover/README.md +27 -1
- package/02-primitives/popover/demo.html +45 -0
- package/02-primitives/progress/README.md +4 -0
- package/02-primitives/progress/demo.html +25 -0
- package/02-primitives/select/README.md +12 -0
- package/02-primitives/select/demo.html +46 -0
- package/02-primitives/separator/README.md +3 -1
- package/02-primitives/skeleton/demo.html +28 -0
- package/02-primitives/switch/README.md +14 -0
- package/03-patterns/accordion/README.md +17 -0
- package/03-patterns/content/demo.html +20 -0
- package/03-patterns/drawer/README.md +12 -0
- package/03-patterns/drawer/demo.html +36 -0
- package/03-patterns/dropdown/README.md +15 -0
- package/03-patterns/dropdown/demo.html +39 -0
- package/03-patterns/list/demo.html +48 -0
- package/03-patterns/nav/demo.html +34 -1
- package/03-patterns/overlay/README.md +3 -3
- package/03-patterns/pagination/README.md +14 -0
- package/03-patterns/pagination/demo.html +40 -0
- package/03-patterns/reveal/README.md +15 -0
- package/03-patterns/reveal/demo.html +24 -0
- package/03-patterns/states/README.md +1 -1
- package/03-patterns/states/demo.html +25 -1
- package/03-patterns/tabs/README.md +15 -0
- package/03-patterns/tooltip/README.md +13 -0
- package/03-patterns/tooltip/demo.html +27 -0
- package/03-patterns/tree/README.md +16 -0
- package/03-patterns/tree/demo.html +43 -0
- package/04-recipes/analysis-report/README.md +16 -0
- package/04-recipes/analysis-report/demo.html +34 -0
- package/04-recipes/data-showcase/README.md +12 -0
- package/04-recipes/data-showcase/demo.html +29 -0
- package/04-recipes/detail-page/README.md +13 -0
- package/04-recipes/detail-page/demo.html +28 -0
- package/04-recipes/report/README.md +13 -0
- package/04-recipes/report/demo.html +24 -0
- package/04-recipes/table/README.md +38 -0
- package/04-recipes/table/demo.html +39 -0
- package/CHANGELOG.md +90 -0
- package/CONTRIBUTING.md +8 -1
- package/ai/components.json +38 -10
- package/dist/01-tokens/page.css +1 -1
- package/dist/COSTS.md +1 -1
- package/index.html +1 -1
- package/package.json +1 -1
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
<style>
|
|
15
15
|
.row { display: flex; gap: var(--sp-4); flex-wrap: wrap; align-items: center; }
|
|
16
16
|
.pad { padding: var(--sp-9) 0; }
|
|
17
|
+
.tt-field { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); }
|
|
18
|
+
.tt-label { font-weight: 500; }
|
|
19
|
+
.tt-icon { color: var(--text-tertiary); cursor: help; }
|
|
20
|
+
.tt-real { font-size: var(--fs-xs); color: var(--text-secondary); }
|
|
21
|
+
.tt-hint { margin: var(--sp-2) 0 0; font-size: var(--fs-xs); color: var(--text-tertiary); }
|
|
17
22
|
</style>
|
|
18
23
|
</head>
|
|
19
24
|
<body class="page page">
|
|
@@ -57,6 +62,28 @@
|
|
|
57
62
|
<button class="btn" id="good">导出 CSV</button>
|
|
58
63
|
</div>
|
|
59
64
|
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
<h2 class="rule-bottom">对比:错写法 vs 本库写法</h2>
|
|
68
|
+
<div class="cmp">
|
|
69
|
+
<div class="cmp__pane cmp__bad">
|
|
70
|
+
<h3>❌ 常见写法:关键信息只放在气泡里</h3>
|
|
71
|
+
<div class="tt-field" aria-hidden="true">
|
|
72
|
+
<span class="tt-label">账期</span>
|
|
73
|
+
<span class="tt-icon" title="按合同约定的账期填写,自然日">ⓘ</span>
|
|
74
|
+
</div>
|
|
75
|
+
<p class="tt-hint">(把鼠标停在那颗 ⓘ 上才看得到说明)</p>
|
|
76
|
+
<p class="cmp__why">触屏没有 hover,键盘用户也未必会停留 —— 这条说明对一半以上的读者等于不存在。判断标准很硬:<b>气泡里的字不能是"必须知道才能填对"的信息</b>。</p>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="cmp__pane cmp__good">
|
|
79
|
+
<h3>✅ 本库:该看见的写在页面上</h3>
|
|
80
|
+
<div class="tt-field" aria-hidden="true">
|
|
81
|
+
<span class="tt-label">账期</span>
|
|
82
|
+
<span class="tt-real">按合同约定的账期填写(自然日)</span>
|
|
83
|
+
</div>
|
|
84
|
+
<p class="cmp__why">tooltip 只用来<b>补一句</b>(快捷键、单位、来源),不用来补一个字段能不能填对。真的需要解释,就写在它旁边。</p>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
60
87
|
</main>
|
|
61
88
|
|
|
62
89
|
<script src="tooltip.js"></script>
|
|
@@ -89,6 +89,22 @@ const t = Tree.create(元素, { label: '目录' });
|
|
|
89
89
|
|
|
90
90
|
`ai/components.json` 里 `tree` 的 `behaviorDebt` 为空。
|
|
91
91
|
|
|
92
|
+
## 反例
|
|
93
|
+
|
|
94
|
+
- ❌ **↑↓ 只移动焦点、←→ 只展开不移动焦点** —— APG 是**两段式**:↑↓ 移动焦点,←→ 展开/收起
|
|
95
|
+
**并带着焦点走**。只做一半,键盘用户会觉得"按了没反应"
|
|
96
|
+
- ❌ **每个 `tree__item` 都 `tabindex="0"`** —— 整棵树只占**一个** Tab 位(roving tabindex);
|
|
97
|
+
否则穿过 200 个节点要按 200 次 Tab
|
|
98
|
+
- ❌ **只靠旋转箭头表示展开/收起** —— 必须有**三态形状线索**(`tree__marker`):
|
|
99
|
+
旋转只能看出"变过",看不出"现在是哪一态"
|
|
100
|
+
- ❌ **RTL 下收起箭头不翻向** —— 阿拉伯语用户看到的是一个指错方向的符号;
|
|
101
|
+
`tree.css` 里那条 `[dir="rtl"]` 就是为此
|
|
102
|
+
- ❌ **用 `margin` 做层级缩进** —— 缩进用 padding:`margin` 会把点击区一起缩窄,深层的节点点不中
|
|
103
|
+
- ❌ **把 ←→ 交给"左右移动"处理** —— 树里 ←→ 是展开/收起(APG 两段式),
|
|
104
|
+
当成左右移动会被方向键库先吃掉
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
92
108
|
## 门禁
|
|
93
109
|
|
|
94
110
|
`05-audit/tree-check.js`
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
color: var(--text-secondary); min-height: 3em;
|
|
25
25
|
}
|
|
26
26
|
.frame { padding: var(--sp-3); border: 1px solid var(--border-decor); border-radius: var(--r-md); }
|
|
27
|
+
.tr-demo { list-style: none; margin: 0; padding: 0; font-size: var(--fs-sm); }
|
|
28
|
+
.tr-demo ul { list-style: none; margin: 0; padding-inline-start: 1.4em; }
|
|
29
|
+
.tr-one { display: inline-block; width: 1em; font-size: .8em;
|
|
30
|
+
color: var(--text-tertiary); text-align: center; }
|
|
27
31
|
</style>
|
|
28
32
|
</head>
|
|
29
33
|
<body class="page page">
|
|
@@ -52,6 +56,45 @@
|
|
|
52
56
|
<div id="t2"></div>
|
|
53
57
|
</div>
|
|
54
58
|
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
<h2 class="rule-bottom">对比:错写法 vs 本库写法</h2>
|
|
62
|
+
<div class="cmp">
|
|
63
|
+
<div class="cmp__pane cmp__bad">
|
|
64
|
+
<h3>❌ 常见写法:靠"旋转"表示状态</h3>
|
|
65
|
+
<ul class="tr-demo" role="tree" aria-label="文件树示例" aria-hidden="true">
|
|
66
|
+
<li class="tree__item" aria-expanded="true">
|
|
67
|
+
<div class="tree__node"><span class="tr-one">▸</span><span class="tree__label">src</span></div>
|
|
68
|
+
<ul role="group">
|
|
69
|
+
<li class="tree__item" aria-expanded="false">
|
|
70
|
+
<div class="tree__node"><span class="tr-one">▸</span><span class="tree__label">components</span></div>
|
|
71
|
+
</li>
|
|
72
|
+
<li class="tree__item">
|
|
73
|
+
<div class="tree__node"><span class="tr-one">▸</span><span class="tree__label">index.js</span></div>
|
|
74
|
+
</li>
|
|
75
|
+
</ul>
|
|
76
|
+
</li>
|
|
77
|
+
</ul>
|
|
78
|
+
<p class="cmp__why">三个节点长得一模一样:已展开的 src、收起的 components、叶子的 index.js 全是 ▸。旋转只能表达"变过",表达不了"现在是哪一态"。</p>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="cmp__pane cmp__good">
|
|
81
|
+
<h3>✅ 本库:三态三种字形</h3>
|
|
82
|
+
<ul class="tr-demo" role="tree" aria-label="文件树示例" aria-hidden="true">
|
|
83
|
+
<li class="tree__item" aria-expanded="true">
|
|
84
|
+
<div class="tree__node"><span class="tree__marker"></span><span class="tree__label">src</span></div>
|
|
85
|
+
<ul role="group">
|
|
86
|
+
<li class="tree__item" aria-expanded="false">
|
|
87
|
+
<div class="tree__node"><span class="tree__marker"></span><span class="tree__label">components</span></div>
|
|
88
|
+
</li>
|
|
89
|
+
<li class="tree__item">
|
|
90
|
+
<div class="tree__node"><span class="tree__marker"></span><span class="tree__label">index.js</span></div>
|
|
91
|
+
</li>
|
|
92
|
+
</ul>
|
|
93
|
+
</li>
|
|
94
|
+
</ul>
|
|
95
|
+
<p class="cmp__why"><code>tree.css</code> 按 <code>aria-expanded</code> 给三种字形:▼ 展开 / ▶ 收起 / · 叶子。形状本身就是信息,不依赖动画。</p>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
55
98
|
</main>
|
|
56
99
|
|
|
57
100
|
<script src="tree.js"></script>
|
|
@@ -78,3 +78,19 @@ python -m http.server 8000 # 仓库根
|
|
|
78
78
|
|
|
79
79
|
页面里的实验数据**全部是演示用示例数据**,不是真实实验结果。
|
|
80
80
|
留出这条是因为:「长得像真实数据」的示例最容易被误引用。
|
|
81
|
+
|
|
82
|
+
## 反例
|
|
83
|
+
|
|
84
|
+
- ❌ **栅格列写 `1fr` 而不是 `minmax(0, 1fr)`** —— 长表格、长代码会把列撑开,整页横向溢出。
|
|
85
|
+
这是 Grid 的经典陷阱,`analysis-report.css` 里两处都写成 `minmax(0, 1fr)`
|
|
86
|
+
- ❌ **先做桌面并排、再用媒体查询缩回单栏** —— 默认就该是单栏,并排是宽屏**才发生**的事。
|
|
87
|
+
反过来做,窄屏上得到的是"缩小的桌面版"
|
|
88
|
+
- ❌ **`position: sticky` 的辅助栏不配 `align-self: start`** —— 在 grid 里 sticky 不生效,
|
|
89
|
+
那一栏会跟着页面一起滚走
|
|
90
|
+
- ❌ **再另造一个"侧栏卡片"** —— 直接复用 `card.css`;重复造会在换主题时多一个不一致的源头
|
|
91
|
+
- ❌ **用 inline style 写字号和颜色** —— inline 的优先级高于一切样式表(INVARIANT I-4),
|
|
92
|
+
换肤时改不动,只能一路 `!important`
|
|
93
|
+
- ❌ **把组件 CSS 引在骨架之前** —— 顺序反了就要靠 `!important` 抢优先级;
|
|
94
|
+
"骨架在组件之前"这条是有门禁守着的
|
|
95
|
+
|
|
96
|
+
---
|
|
@@ -18,6 +18,17 @@
|
|
|
18
18
|
<link rel="stylesheet" href="../../09-assets/scientific-plot/scientific-plot.css">
|
|
19
19
|
|
|
20
20
|
<link rel="stylesheet" href="analysis-report.css">
|
|
21
|
+
<style>
|
|
22
|
+
.ar-g { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); }
|
|
23
|
+
.ar-g--ok { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
|
|
24
|
+
.ar-cell { padding: var(--sp-2); background: var(--surface-raised);
|
|
25
|
+
border: 1px solid var(--border-decor); border-radius: var(--r-xs);
|
|
26
|
+
font-size: var(--fs-xs); }
|
|
27
|
+
/* 反例的关键:这里**不能**写 overflow:hidden —— 一写,min-content 就变 0,
|
|
28
|
+
那个"列被长内容撑开"的毛病就被自己抹平了(第一版就是这么写坏的) */
|
|
29
|
+
.ar-long { font-family: var(--font-mono, monospace); white-space: nowrap; }
|
|
30
|
+
.ar-g--ok .ar-long { overflow: hidden; text-overflow: ellipsis; }
|
|
31
|
+
</style>
|
|
21
32
|
</head>
|
|
22
33
|
<body class="page">
|
|
23
34
|
<main class="wrap report">
|
|
@@ -222,6 +233,29 @@
|
|
|
222
233
|
</ol>
|
|
223
234
|
</footer>
|
|
224
235
|
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
<h2 class="rule-bottom">对比:错写法 vs 本库写法</h2>
|
|
239
|
+
<!-- cmp--clip:这一块演示的就是"长串把列撑开",栏内必须允许算得比栏宽更宽;
|
|
240
|
+
越出栏框的部分裁掉(不裁的话 320px 下整页横向溢出 64px,WCAG 1.4.10 红)。 -->
|
|
241
|
+
<div class="cmp cmp--clip">
|
|
242
|
+
<div class="cmp__pane cmp__bad">
|
|
243
|
+
<h3>❌ 常见写法:栅格列写 <code>1fr</code></h3>
|
|
244
|
+
<div class="ar-g" aria-hidden="true">
|
|
245
|
+
<div class="ar-cell">正文一栏:营收同比 +18%。</div>
|
|
246
|
+
<div class="ar-cell ar-long">SH600519-SH000001-SZ300750-SH601318-SZ000858</div>
|
|
247
|
+
</div>
|
|
248
|
+
<p class="cmp__why">右栏里一串不肯断的长代码把列撑开了:它不换行、也不省略,整页横向溢出 —— 而外层容器并<b>没有</b>写错,错的是列定义。</p>
|
|
249
|
+
</div>
|
|
250
|
+
<div class="cmp__pane cmp__good">
|
|
251
|
+
<h3>✅ 本库:<code>minmax(0, 1fr)</code></h3>
|
|
252
|
+
<div class="ar-g ar-g--ok" aria-hidden="true">
|
|
253
|
+
<div class="ar-cell">正文一栏:营收同比 +18%。</div>
|
|
254
|
+
<div class="ar-cell ar-long">SH600519-SH000001-SZ300750-SH601318-SZ000858</div>
|
|
255
|
+
</div>
|
|
256
|
+
<p class="cmp__why"><code>1fr</code> 的最小值是 <code>auto</code>(即"内容最小宽度"),所以挡不住长内容。<code>minmax(0, 1fr)</code> 把下限按到 0,列宽才真正受控;再配一句 <code>text-overflow: ellipsis</code>,内容就收在格子里。</p>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
225
259
|
</main>
|
|
226
260
|
|
|
227
261
|
<script src="../../09-assets/scientific-plot/scientific-plot.js"></script>
|
|
@@ -43,3 +43,15 @@ python -m http.server 8000
|
|
|
43
43
|
|
|
44
44
|
页面内所有数值均为**示例数据**,不构成任何业务或科研结论。
|
|
45
45
|
留这句是因为「长得像真实数据」的示例最容易被误引用。
|
|
46
|
+
|
|
47
|
+
## 反例
|
|
48
|
+
|
|
49
|
+
- ❌ **单位与数字同字号同色** —— "1,284.6 亿元" 里"亿元"只是量级标记,却和数字抢同一层注意力;本库把单位降一档(`--fs-sm` + 次级色),数字用 `num` 等宽(纵向才对得齐)
|
|
50
|
+
- ❌ **把这四个当成"同一种图表的四种皮肤"** —— 它们共享令牌与容器,但**不共享**坐标规则与数据格式,
|
|
51
|
+
是四个用途。换皮肤换不来正确的表达
|
|
52
|
+
- ❌ **用 `table` 回答"涨还是跌"** —— 表格给的是具体值,趋势要看形状;
|
|
53
|
+
那是 `sparkline` 的活,用表看趋势要一行行读数字
|
|
54
|
+
- ❌ **用完整坐标系画三五个点** —— 坐标轴、刻度、网格是为"值落在哪、误差多大"服务的;
|
|
55
|
+
几个点的走向用迷你趋势图就够,画坐标系反而让人以为有精度
|
|
56
|
+
|
|
57
|
+
---
|
|
@@ -34,6 +34,14 @@
|
|
|
34
34
|
屏幕阅读器会把它读成「图 1 的说明」,语义本身就是信息。 */
|
|
35
35
|
.figbox figcaption { margin-top: var(--sp-2); font-size: var(--fs-xs);
|
|
36
36
|
color: var(--text-tertiary); }
|
|
37
|
+
.ds-stat { display: flex; align-items: baseline; gap: var(--sp-2);
|
|
38
|
+
padding: var(--sp-3); background: var(--surface-raised);
|
|
39
|
+
border: 1px solid var(--border-decor); border-radius: var(--r-sm); }
|
|
40
|
+
.ds-k { font-size: var(--fs-xs); color: var(--text-secondary); margin-inline-end: auto; }
|
|
41
|
+
.ds-v { font-size: var(--fs-lg); font-weight: 600; }
|
|
42
|
+
/* 反例专用:单位跟数字同字号同色("抢同一层注意力"就是这个样子) */
|
|
43
|
+
.ds-v .ds-u--flat { font-size: inherit; color: inherit; } /* 特异性要比 .ds-u 高 */
|
|
44
|
+
.ds-u { font-size: var(--fs-sm); color: var(--text-secondary); }
|
|
37
45
|
</style>
|
|
38
46
|
</head>
|
|
39
47
|
<body class="page">
|
|
@@ -215,6 +223,27 @@
|
|
|
215
223
|
</table>
|
|
216
224
|
</div>
|
|
217
225
|
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
<h2 class="rule-bottom">对比:错写法 vs 本库写法</h2>
|
|
229
|
+
<div class="cmp">
|
|
230
|
+
<div class="cmp__pane cmp__bad">
|
|
231
|
+
<h3>❌ 常见写法:单位与数字同字号同色</h3>
|
|
232
|
+
<div class="ds-stat" aria-hidden="true">
|
|
233
|
+
<span class="ds-k">营业收入</span>
|
|
234
|
+
<span class="ds-v"><span class="num">1,284.6</span><span class="ds-u ds-u--flat">亿元</span></span>
|
|
235
|
+
</div>
|
|
236
|
+
<p class="cmp__why">"亿元"只是个量级标记,却和 1,284.6 抢同一层注意力:读者先读到的是四个字,而不是那个数。</p>
|
|
237
|
+
</div>
|
|
238
|
+
<div class="cmp__pane cmp__good">
|
|
239
|
+
<h3>✅ 本库:数字当主角,单位退一档</h3>
|
|
240
|
+
<div class="ds-stat" aria-hidden="true">
|
|
241
|
+
<span class="ds-k">营业收入</span>
|
|
242
|
+
<span class="ds-v"><span class="num">1,284.6</span><span class="ds-u">亿元</span></span>
|
|
243
|
+
</div>
|
|
244
|
+
<p class="cmp__why">数字用 <code>num</code>(等宽数字,纵向才对得齐),单位降一档字号与颜色。一屏里有十几个数字时,这个差别决定读者能不能扫。</p>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
218
247
|
</main>
|
|
219
248
|
|
|
220
249
|
<script src="../../09-assets/sparkline/sparkline.js"></script>
|
|
@@ -91,3 +91,16 @@ python 05-audit/no-data-gate.py # 无数据态三条规则
|
|
|
91
91
|
一旦把某个业务的字段写进通用库,库的边界就没了。
|
|
92
92
|
- **不做图表**:指标卡只放数字。要图请用 `09-assets/` 的图表组件。
|
|
93
93
|
- **不做标签页 / 折叠**:那是 `03-patterns/` 的组件,这里只给骨架。
|
|
94
|
+
|
|
95
|
+
## 反例
|
|
96
|
+
|
|
97
|
+
- ❌ **缺的字段写成 `0`** —— `0` 是一个真实的值,用户会拿它去算同比。缺就是缺:
|
|
98
|
+
写「未披露」+ 弱化色
|
|
99
|
+
- ❌ **缺的字段直接把节点删掉** —— 三个变体的 DOM 结构必须完全一致(节点数量与嵌套),
|
|
100
|
+
删节点会让同一类页面越改越不像,最后没人能说清"这页该长什么样"
|
|
101
|
+
- ❌ **无数据时隐藏整块** —— 不隐藏、不冒充零,**必须写清原因**。
|
|
102
|
+
空白让人以为是加载失败,反而会去刷新
|
|
103
|
+
- ❌ **三个变体各写一套类名** —— 允许变的是文案、数值、说明块;类名与语义标签不许变
|
|
104
|
+
- ❌ **换肤时改类名** —— 色对挂在 `section` 上,改类名等于换了一套结构,之后没法对比
|
|
105
|
+
|
|
106
|
+
---
|
|
@@ -18,6 +18,13 @@
|
|
|
18
18
|
.dp-link__t { font-weight: 600; }
|
|
19
19
|
.dp-link__d { display: block; margin-top: 4px; font-size: var(--fs-sm);
|
|
20
20
|
color: var(--text-secondary); }
|
|
21
|
+
.dp-kpi { display: flex; align-items: baseline; gap: var(--sp-2);
|
|
22
|
+
padding: var(--sp-3); background: var(--surface-raised);
|
|
23
|
+
border: 1px solid var(--border-decor); border-radius: var(--r-sm); }
|
|
24
|
+
.dp-kpi__k { font-size: var(--fs-xs); color: var(--text-secondary); }
|
|
25
|
+
.dp-kpi__v { font-size: var(--fs-lg); font-weight: 600; }
|
|
26
|
+
.dp-kpi__u { font-size: var(--fs-xs); color: var(--text-secondary); }
|
|
27
|
+
.detail-null__v { font-size: var(--fs-md); font-weight: 500; color: var(--text-tertiary); }
|
|
21
28
|
</style>
|
|
22
29
|
</head>
|
|
23
30
|
<body class="page">
|
|
@@ -50,6 +57,27 @@
|
|
|
50
57
|
② 皮肤挂在 <code>section</code> 上,不挂 <code>body</code>;<br>
|
|
51
58
|
③ <strong>DOM 不许变</strong>,字段缺失是值缺失,不是节点缺失。
|
|
52
59
|
</p>
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
<h2 class="rule-bottom">对比:错写法 vs 本库写法</h2>
|
|
63
|
+
<div class="cmp">
|
|
64
|
+
<div class="cmp__pane cmp__bad">
|
|
65
|
+
<h3>❌ 常见写法:缺的字段写 0</h3>
|
|
66
|
+
<div class="dp-kpi" aria-hidden="true">
|
|
67
|
+
<span class="dp-kpi__k">研发投入</span>
|
|
68
|
+
<span class="dp-kpi__v"><span class="num">0</span><span class="dp-kpi__u">亿元</span></span>
|
|
69
|
+
</div>
|
|
70
|
+
<p class="cmp__why"><code>0</code> 是一个真实的值:读者会拿它去算"研发强度 = 0",也会拿它去比同比 —— 而这一格其实<b>没有</b>数据。</p>
|
|
71
|
+
</div>
|
|
72
|
+
<div class="cmp__pane cmp__good">
|
|
73
|
+
<h3>✅ 本库:写「未披露」+ 弱化色</h3>
|
|
74
|
+
<div class="dp-kpi" aria-hidden="true">
|
|
75
|
+
<span class="dp-kpi__k">研发投入</span>
|
|
76
|
+
<span class="dp-kpi__v"><span class="detail-null__v">未披露</span></span>
|
|
77
|
+
</div>
|
|
78
|
+
<p class="cmp__why">缺就是缺。同一页里三个变体的 DOM 结构必须完全一致(节点数量与嵌套),所以缺数据时是<b>换文案</b>,不是删节点 —— 删了以后这页越改越不像。</p>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
53
81
|
</main>
|
|
54
82
|
</body>
|
|
55
83
|
</html>
|
|
@@ -174,3 +174,16 @@ bash 05-audit/check-all.sh # 全量
|
|
|
174
174
|
全部读**计算值/几何**而不是 CSS 文本 —— 因为"写了 ≠ 生效"在本系统上翻过车:
|
|
175
175
|
`.rep h2 / .rep h3`(特异度 0,1,1)曾经压过 `.rep__title`(0,1,0),
|
|
176
176
|
使 `--rep-title-fs` 静默失效、三套版式的标题被钉死在同一个字号。
|
|
177
|
+
|
|
178
|
+
## 反例
|
|
179
|
+
|
|
180
|
+
- ❌ **拿它做分页 PDF / 印刷分页** —— 页边距、页眉页脚、页码、跨页控制**一律没有**,
|
|
181
|
+
也不假装有。需要印刷排版,用专门的工具链
|
|
182
|
+
- ❌ **靠改选择器换版式** —— 换版式只改那六个变量(`--rep-measure` / `--rep-body-fs` /
|
|
183
|
+
`--rep-title-fs` / `--rep-lead-fs` / `--rep-body-lh` / `--rep-sec-num`),不改选择器
|
|
184
|
+
- ❌ **再发明第七种字体角色** —— 六个角色(眉题 / 元信息 / 图表说明 / 来源 / 编者注 / 风险披露)
|
|
185
|
+
是**不多不少**的;多一种,读者就要重新学一遍"这行字是什么身份"
|
|
186
|
+
- ❌ **把它当 CMS 或模板引擎** —— 没有内容管理、没有模板继承、没有构建步骤,只有 CSS
|
|
187
|
+
- ❌ **自己写表格样式** —— 复用 `table.css`;两份表格样式在换主题时必然分叉
|
|
188
|
+
|
|
189
|
+
---
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
<link rel="stylesheet" href="report.css">
|
|
14
14
|
<!-- 本页不写内联 <style>:所有版式都来自 report.css。
|
|
15
15
|
内联写成活的那一刻,它就不再是这个系统的一部分了。 -->
|
|
16
|
+
<style>
|
|
17
|
+
.rep-p { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); line-height: 1.7; }
|
|
18
|
+
</style>
|
|
16
19
|
</head>
|
|
17
20
|
<body class="page">
|
|
18
21
|
<main class="wrap">
|
|
@@ -299,6 +302,27 @@
|
|
|
299
302
|
共享基础的六个可变量,以及与 <code>04-recipes/analysis-report</code>(一份具体实例)的分工。
|
|
300
303
|
</p>
|
|
301
304
|
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
<h2 class="rule-bottom">对比:错写法 vs 本库写法</h2>
|
|
308
|
+
<div class="cmp">
|
|
309
|
+
<div class="cmp__pane cmp__bad">
|
|
310
|
+
<h3>❌ 常见写法:来源与正文同一副面孔</h3>
|
|
311
|
+
<div class="rep" aria-hidden="true">
|
|
312
|
+
<p class="rep-p">本季度毛利率 42.1%,环比提升 1.3 个百分点。</p>
|
|
313
|
+
<p class="rep-p">数据来源:公司 2026 年三季报,经本库统一口径重算。</p>
|
|
314
|
+
</div>
|
|
315
|
+
<p class="cmp__why">读者读到第二句才知道这是"出处",而它和正文长得一模一样 —— 分不清哪句是结论、哪句是依据。</p>
|
|
316
|
+
</div>
|
|
317
|
+
<div class="cmp__pane cmp__good">
|
|
318
|
+
<h3>✅ 本库:来源用 <code>rep__cap</code> 这一档角色</h3>
|
|
319
|
+
<div class="rep" aria-hidden="true">
|
|
320
|
+
<p class="rep-p">本季度毛利率 42.1%,环比提升 1.3 个百分点。</p>
|
|
321
|
+
<p class="rep__cap">数据来源:公司 2026 年三季报,经本库统一口径重算。</p>
|
|
322
|
+
</div>
|
|
323
|
+
<p class="cmp__why">report 的六个字体角色(眉题 / 元信息 / 图表说明 / 来源 / 编者注 / 风险披露)是<b>不多不少</b>的。多造一种,读者就要重新学一遍"这行字是什么身份"。</p>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
302
326
|
</main>
|
|
303
327
|
|
|
304
328
|
<script src="../../09-assets/scientific-plot/scientific-plot.js"></script>
|
|
@@ -101,3 +101,41 @@ var COLS = [
|
|
|
101
101
|
python -m http.server 8000
|
|
102
102
|
# http://127.0.0.1:8000/04-recipes/table/demo.html
|
|
103
103
|
```
|
|
104
|
+
|
|
105
|
+
## 配色:与本库 `list` 的约定**不同**(已知,未统一)
|
|
106
|
+
|
|
107
|
+
| 组件 | 类名 | 约定 |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `table` | `num--pos` / `num--neg` | **会计约定**:正 = 绿、负 = 红(负数即"红字") |
|
|
110
|
+
| `list` | `list__value--up` / `--down` | **市场约定**:涨 = 红、跌 = 绿(A 股惯例) |
|
|
111
|
+
|
|
112
|
+
两种约定并存不是笔误,是因为两处的数是两种东西:
|
|
113
|
+
|
|
114
|
+
- 表格里多是**量**(营收、毛利率、净利润)—— 负数是"红字",会计惯例;
|
|
115
|
+
- 列表里多是**涨跌**(涨跌幅、日变动)—— A 股惯例是涨红跌绿。
|
|
116
|
+
|
|
117
|
+
⚠️ **真正的麻烦在这里**:把「涨跌幅」这一列塞进 `table` 时,两种约定会打架 ——
|
|
118
|
+
负的涨跌幅被渲染成红色,读者第一眼读成"涨"。目前**没有解**:
|
|
119
|
+
|
|
120
|
+
- 加一套 `num--up` / `num--down`(市场约定)是候选,但那会让 `table` 有四组颜色类;
|
|
121
|
+
- 或者由调用方显式指定语义(`data-polarity="market"`),但那要改契约。
|
|
122
|
+
|
|
123
|
+
在决定之前,这一条就写在这儿 —— 一个库里有两种配色约定而不说明,
|
|
124
|
+
比约定本身选错更糟。
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
## 反例
|
|
128
|
+
|
|
129
|
+
- ❌ **靠数值大小猜语义** —— 不能用"小于 1 就乘 100"。`0.25` 是比例还是普通测量值,
|
|
130
|
+
只能由列定义的 `format` 说
|
|
131
|
+
- ❌ **给"量"的正数加 `+`** —— 营收、成本、毛利率这类量没有 `+`;只有 `signed-percent`
|
|
132
|
+
这类"变化量"才加。满屏 `+` 会让读者以为每个数都在变
|
|
133
|
+
- ❌ **负数用连字符 `-`** —— 用真减号 `−`;连字符在等宽数字里对不齐,也容易被当成项目符号
|
|
134
|
+
- ❌ **排序状态放在按钮上** —— 要放 `<th aria-sort="ascending|descending">`;
|
|
135
|
+
放在按钮上读屏不会报告"这一列正按什么排序"
|
|
136
|
+
- ❌ **正负只靠红绿** —— 颜色之外必须有 `+` / `−` 符号(WCAG 1.4.1)
|
|
137
|
+
- ❌ **粘性表头配 `border-collapse: collapse`** —— `separate` 是 sticky 生效的前提,
|
|
138
|
+
用 collapse 表头不会粘住
|
|
139
|
+
- ❌ **拿它当虚拟滚动表格用** —— 本组件不做虚拟滚动;超过 200 行请配分页
|
|
140
|
+
|
|
141
|
+
---
|
|
@@ -14,6 +14,12 @@
|
|
|
14
14
|
<style>
|
|
15
15
|
.toolbar { display: flex; gap: var(--sp-2); margin: 0 0 var(--sp-3); flex-wrap: wrap; }
|
|
16
16
|
.section-note { margin: 0 0 var(--sp-3); }
|
|
17
|
+
.tb-demo { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
|
|
18
|
+
.tb-demo th, .tb-demo td { padding: var(--sp-2) var(--sp-3); text-align: start;
|
|
19
|
+
border-bottom: 1px solid var(--border-decor); }
|
|
20
|
+
.tb-demo th { font-weight: 500; color: var(--text-secondary); font-size: var(--fs-xs); }
|
|
21
|
+
/* 反例专用:把库自动生成的 +/− 关掉,只留颜色(这就是"只靠红绿") */
|
|
22
|
+
.tb-bad .num--pos::before, .tb-bad .num--neg::before { content: none; }
|
|
17
23
|
</style>
|
|
18
24
|
</head>
|
|
19
25
|
<body class="page">
|
|
@@ -86,6 +92,39 @@
|
|
|
86
92
|
</p>
|
|
87
93
|
<div id="escproof"></div>
|
|
88
94
|
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
<h2 class="rule-bottom">对比:错写法 vs 本库写法</h2>
|
|
98
|
+
<div class="cmp">
|
|
99
|
+
<div class="cmp__pane cmp__bad">
|
|
100
|
+
<h3>❌ 常见写法:只靠红绿 + 连字符</h3>
|
|
101
|
+
<div class="table tb-bad" aria-hidden="true">
|
|
102
|
+
<table class="tb-demo">
|
|
103
|
+
<thead><tr><th scope="col">板块</th><th scope="col" class="num">涨跌幅</th></tr></thead>
|
|
104
|
+
<tbody>
|
|
105
|
+
<tr><td>半导体</td><td class="num num--neg">-1.05%</td></tr>
|
|
106
|
+
<tr><td>白酒</td><td class="num num--pos">3.21%</td></tr>
|
|
107
|
+
<tr><td>光伏</td><td class="num num--neg">-12.40%</td></tr>
|
|
108
|
+
</tbody>
|
|
109
|
+
</table>
|
|
110
|
+
</div>
|
|
111
|
+
<p class="cmp__why">涨的那行没有 <code>+</code>,跌的用连字符 <code>-</code>:灰度打印、色觉障碍、以及"只扫一列符号"的读法,全都不成立;连字符还比真减号窄,一列数字的个位对不齐。</p>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="cmp__pane cmp__good">
|
|
114
|
+
<h3>✅ 本库:符号 + 真减号 <code>−</code></h3>
|
|
115
|
+
<div class="table" aria-hidden="true">
|
|
116
|
+
<table class="tb-demo">
|
|
117
|
+
<thead><tr><th scope="col">板块</th><th scope="col" class="num">涨跌幅</th></tr></thead>
|
|
118
|
+
<tbody>
|
|
119
|
+
<tr><td>半导体</td><td class="num num--neg">1.05%</td></tr>
|
|
120
|
+
<tr><td>白酒</td><td class="num num--pos">3.21%</td></tr>
|
|
121
|
+
<tr><td>光伏</td><td class="num num--neg">12.40%</td></tr>
|
|
122
|
+
</tbody>
|
|
123
|
+
</table>
|
|
124
|
+
</div>
|
|
125
|
+
<p class="cmp__why">颜色是<b>辅助</b>,符号才是信息(WCAG 1.4.1)。符号由 <code>.table .num--pos::before</code> / <code>.num--neg::before</code> 生成 —— 数据里不用手拼 <code>+</code>,也就不会有人漏掉;减号用的是 U+2212,不是连字符。</p>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
89
128
|
</main>
|
|
90
129
|
|
|
91
130
|
<script>
|
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,96 @@
|
|
|
16
16
|
|
|
17
17
|
(无)
|
|
18
18
|
|
|
19
|
+
## [0.11.11] - 2026-10-29
|
|
20
|
+
|
|
21
|
+
**反例从"写着"走到"看得见"**。0.11.10 让 33 个组件都写清了「什么时候不该用」,
|
|
22
|
+
但那 196 条只存在于 README 的文字里 —— 读者得自己在脑子里把"错的样子"还原出来,
|
|
23
|
+
还原不出来的那部分就等于没写。这一版把反例摆进示例页:**带 demo 的 32 个组件里,
|
|
24
|
+
24 个现在是左右并排的「错写法 / 本库写法」**,每块底下跟一句为什么。
|
|
25
|
+
改之前这个数字是 **10 / 32**(数出来的是 22 个页面缺可见反例)。
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **22 个组件页新增可见对照块**,覆盖 `02-primitives` 6 个、`03-patterns` 10 个、
|
|
30
|
+
`04-recipes` 5 个,另有 `choice` 的旧反例块补上了标题(没有标题,读者不知道那块在演示什么)。
|
|
31
|
+
现在带 demo 的 32 个组件里,**24 个是并排两栏**(`02-primitives` 9 / `03-patterns` 10 /
|
|
32
|
+
`04-recipes` 5),**8 个沿用既有的 `.box.bad`**(badge / choice / separator / switch /
|
|
33
|
+
accordion / form-validation / overlay / tabs)。每一块的理由都能指回本库的具体位置:
|
|
34
|
+
`button.css` 的一条注释、`combobox.js` 的一个分支、某道门禁守的一条规则
|
|
35
|
+
—— 没有一条是"看起来不专业"这种正确但学不到东西的话。
|
|
36
|
+
- `05-audit/demo-counterexample-gate.py` —— 判「反例能不能被看见」。它和 0.11.10 的
|
|
37
|
+
`do-dont-gate.py` 守的是两层:那边判**写没写**(README 里有没有章节、条目够不够、
|
|
38
|
+
有没有编造标识符),这边判**看不看得见**(demo 里有没有反例块、有没有被 `hidden` 藏起来、
|
|
39
|
+
块后面有没有标题说明它在演示什么)。7 条自检,5 条必须红。
|
|
40
|
+
它的组件名单不另写一份,`importlib` 读 `coverage-gate.py` 的 `LAYOUT_PAGES`
|
|
41
|
+
—— 同一个事实写在两处,早晚有一天两处不一样。
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- **`.cmp` 收编进 `01-tokens/page.css`**(此前 `button` / `card` / `input` 三页各写一遍)。
|
|
46
|
+
判据是"语义相同才收":那三页的栅格意图一致(`1.55fr 1fr`)、gap 与断点却三种写法,
|
|
47
|
+
是同一个东西的无意分叉;而 `.row` 15 页 14 种写法**不收** —— 那些是语义不同的东西
|
|
48
|
+
(工具条 / 按钮排 / 元信息行)。不收的理由写在 `page.css` 的注释里,免得下一个人再问一遍。
|
|
49
|
+
- 对照块断点定在 **640px 而不是 720px**:文档页里的活标本 iframe 实测只有 734px 宽,
|
|
50
|
+
720 的断点等于"再窄一点就叠成单栏",而叠成单栏,"并排"这件事本身就不存在了。
|
|
51
|
+
- **栅格改用 `minmax(0, 1fr)`**:第一版照旧三页抄了 `1fr`,结果 4 个页面在 320px /
|
|
52
|
+
834px / RTL 阿拉伯语膨胀后横向溢出 81–155px。`1fr` 的下限是 `auto`(内容最小宽度),
|
|
53
|
+
一栏里有不换行的长串就顶破整页 —— 这条恰恰是 `04-recipes/analysis-report` 那一页
|
|
54
|
+
正在教别人的东西。
|
|
55
|
+
- `a11y-scan.js` 扫描期间跳过 `.cmp__bad`。漏掉这一条的后果不是"少报一个错",
|
|
56
|
+
而是**故意写坏的那一栏会把整页判红** —— 于是没人再敢写反例。
|
|
57
|
+
正例栏不隐藏:它示范的就是"该怎么写",必须能正常操作;反例栏里可交互的元素
|
|
58
|
+
加了 `tabindex="-1"`(`aria-hidden` 只移出无障碍树,**不移出 Tab 序列**)。
|
|
59
|
+
|
|
60
|
+
### 跟着改的门禁(判据本身有问题,不是演示块有问题)
|
|
61
|
+
|
|
62
|
+
- `pagination` 的 ⑤/⑨ 从"全页取样"收紧到 `[data-pagination]`:判「每个页码都有
|
|
63
|
+
aria-label」「槽位数 ≤7」时,那两块**静态**页码条(12 个 vs 6 个槽位)被当成了被测对象
|
|
64
|
+
—— 而它们正是拿来演示这两个数字的。
|
|
65
|
+
- `states-check` 的「空状态给出下一步」:排除反例区,并顺手把"只看第一个空状态"
|
|
66
|
+
改成"看全部"(原来页面里第二个空状态没出口也照样过关,那才是这条判据的真漏洞)。
|
|
67
|
+
- `refs` 的报错行原来只给 `demo.html` —— 库里 6 个同名文件,认不出是哪一个。
|
|
68
|
+
根因是 `commonpath` 在参数含仓库根的 `index.html` 时返回空串、被当成假值,
|
|
69
|
+
于是"显示父目录"那段代码**从来没生效过**。
|
|
70
|
+
|
|
71
|
+
### 性能
|
|
72
|
+
|
|
73
|
+
- CSS 合计预算 124 → **125 KB**(实测 +0.83 KB,剥注释后)。
|
|
74
|
+
这次上调**没有"规定动作"级别的理由**,就是一次功能采购,所以 `perf-gate.py`
|
|
75
|
+
里写明了:下次撞线先删等量未引用规则,再来改这个数字。
|
|
76
|
+
|
|
77
|
+
### 已知未解(写在这里,不假装解决了)
|
|
78
|
+
|
|
79
|
+
- **同一页能看到两套相反的涨跌配色**:`04-recipes/table` 用会计约定(正绿负红),
|
|
80
|
+
`03-patterns/list` 用 A 股约定(涨红跌绿)。这一版**没有改** —— 改颜色语义是破坏性变更,
|
|
81
|
+
得单独一版做迁移说明。现状如实记在 `04-recipes/table/README.md` 里。
|
|
82
|
+
- **真机读屏(NVDA / VoiceOver)仍未执行**。自动化能证明"每个控件有可访问名",
|
|
83
|
+
证明不了"念出来听得懂" —— 后者只能人听。这一项在 `docs/ACCESSIBILITY.md` 里就是那么写的。
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## [0.11.10] - 2026-10-29
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
|
|
91
|
+
- **每个组件现在都写清了「什么时候不该用」**。此前 33 个组件里只有 11 个有反例章,
|
|
92
|
+
其余只写"✅ 这么用"—— 一份只写正例的文档,读者学不到边界。新增 20 章、112 条
|
|
93
|
+
(全库现有 195 条),每条的依据都能在本库源码里指到具体位置:
|
|
94
|
+
`button.css` 的一条注释、`combobox.js` 的一个分支、某道门禁守的一条规则。
|
|
95
|
+
- `05-audit/do-dont-gate.py` —— 反例章的门禁。它**不判"理由对不对"**(那是判断题),
|
|
96
|
+
只判两件机器能抓的事:章节在、条目够;以及**反例里提到的本库标识符必须真实存在**
|
|
97
|
+
(修饰符类名 / CSS 变量 / 文件路径)。编造的反例恰恰会在这里露馅:一个人可以凭想象
|
|
98
|
+
写出流畅的理由,但写不出一个真实存在的类名。9 条自检,其中 5 条必须红。
|
|
99
|
+
|
|
100
|
+
### Changed
|
|
101
|
+
|
|
102
|
+
- 章节标题按**语义**识别,不按字面:`## 反例` / `## 两个反例` / `## 反模式` /
|
|
103
|
+
`## 何时**不该**用` 都算。要求统一标题的后果,是让人为了过门禁去改文案。
|
|
104
|
+
- 已有章节里 6 条"只有结论、没有理由"的条目补全了理由
|
|
105
|
+
(`overlay` 的「见上」「混乱」「廉价感」、`states` 的「死路」、`card` 的「游戏感」)。
|
|
106
|
+
- `progress` 新增的四条并入原有的「何时不该用」,没有另开一章 ——
|
|
107
|
+
同一个意思写两遍,读者会在两处看到两套说法。
|
|
108
|
+
|
|
19
109
|
## [0.11.9] - 2026-10-29
|
|
20
110
|
|
|
21
111
|
**把「我们说做到的」和「能证明做到的」对齐**。这一版没有新组件,改的全是
|
package/CONTRIBUTING.md
CHANGED
|
@@ -8,7 +8,8 @@ npm run gate # 全量:含浏览器类
|
|
|
8
8
|
npm run gate:fast # 只跑静态层,不用装浏览器
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
全量是 **
|
|
11
|
+
全量是 **194 道门禁**(本机约 15–20 分钟:组件层要起浏览器,还要逐张比 95 张视觉截图)。
|
|
12
|
+
只想确认没改坏静态契约的话用 `gate:fast`,几秒到几分钟。
|
|
12
13
|
|
|
13
14
|
环境依赖只有一套(Node + Chromium),缺了对应的门禁会**跳过**(跳过不算通过):
|
|
14
15
|
|
|
@@ -105,6 +106,12 @@ fix: <一句话说清改了什么、为什么>
|
|
|
105
106
|
两者的差别就是问题的形状(这正是 E41 的发现方式)。
|
|
106
107
|
5. **豁免要写清理由,并列举式。** 「这份代码的使用者控制不了它」是唯一的豁免理由;
|
|
107
108
|
新增豁免必须显式列出来,否则会被抓到 —— 宁可多报一次,也不要默默放过。
|
|
109
|
+
6. **新组件必须写「反例」章。** 至少 3 条,每条说清「不该怎么用 + 为什么」。
|
|
110
|
+
反例里提到的类名、CSS 变量、文件名必须**真实存在** —— `do-dont` 门禁会逐个核。
|
|
111
|
+
这条不是为了凑数:只写"✅ 这么用"的文档,读者学不到边界;
|
|
112
|
+
而边界恰恰是组件库最该交付的东西。标题怎么写都行
|
|
113
|
+
(`## 反例` / `## 反模式` / `## 何时不该用` 都认),内容不能省。
|
|
114
|
+
**不要为了过门禁改文案**:判据认的是"这段话在讲不该怎么用",不是你用哪个标题。
|
|
108
115
|
|
|
109
116
|
## 提 PR 之前
|
|
110
117
|
|