Skip to content

Commit 634af05

Browse files
chaxusclaude
andcommitted
fix(design): one height, one order for every item in the top bar
The language button was 8px shorter than the nav links beside it: the links inherit the body's prose leading (1.65 -> 23.1px) while the trigger set `line-height: 1`, and its tallest child is a 15px globe. So hovering GitHub filled a 39px box and hovering the language name filled a 31px one, in the same row. Both now declare 22px, which is also the height of the theme switch that shares that row on /history. On a phone the same cause ran the other way: the trigger drops its label under 620px, leaving no text line box at all, so it fell back to 31px beside a 38px GitHub link. A `min-height` derived from the padding token holds it. While in there, three more things that had drifted apart in the same bar: - The order was reversed everywhere except the homepage -- language then GitHub on the content pages, /404 and /history; GitHub then language on /. Unified on the homepage's: external link first, preferences last. - /history and /embed-demo scrolled sideways at 390px (+17px and +27px), with the wordmark and a nav label broken onto two lines. They are the two app surfaces, so they carry a theme switch that other pages keep in a footer they do not have, and the row could not afford 137px of wordmark. The bar now shows the mark alone on a phone, on every page, which fits both with room to spare and needed the wordmark wrapped in a span (it was a bare text node CSS could not select). These two pages are not in the sitemap, so mobile-overflow.spec.ts had never seen them. - home.css dropped the GitHub link under 620px to make room for a language trigger "wide enough for Português" -- which has been icon-only on phones for a while. Removed. Plus the /history filter pill, 31px next to a 32px search field. Tests: two cases in language-menu.spec.ts -- every visible item in the bar shares a height and a baseline across five routes on desktop and on a phone, and neither app surface scrolls sideways at 390px. Reverse verified: removing the line-height reddens the desktop case, removing the min-height the phone one, and removing the wordmark rule reddens both the phone case and the overflow case. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 82cb9f6 commit 634af05

13 files changed

Lines changed: 244 additions & 26 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,17 @@ notes. Entries describe what users experience, not internal refactors.
110110

111111
### Fixed
112112

113+
- **The top bar is one row again.** The language button was 8px shorter than
114+
the links beside it, so hovering GitHub and hovering the language name lit up
115+
two differently sized boxes; on a phone it was the other way round. The
116+
language switch also sat on the left of GitHub on every page except the
117+
homepage, where it sat on the right. Same order, same height, everywhere.
118+
- **The saved-documents and embed demo pages no longer scroll sideways on a
119+
phone.** Both carry a theme switch in the top bar that other pages keep in a
120+
footer, and at 390px wide the row ran past the edge of the screen -- the site
121+
name broke onto two lines and the whole page could be dragged left and right.
122+
On a phone the bar now shows the mark without the wordmark, which fits the
123+
row on every page.
113124
- **Safari: opening a file from the homepage landed on an empty editor.** The
114125
homepage hands the file you pick to the editor through this browser's own
115126
storage, and Safari refuses to store a file that way -- so the editor opened

‎bin/pages/render-home.mjs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ ${jsonLd}
211211
<section id="landing-hero">
212212
<header class="bar">
213213
<div class="wrap">
214-
<a class="brand" href="${home}"><span class="logo">D</span>${e(ui.siteName)}</a>
214+
<a class="brand" href="${home}"><span class="logo">D</span><span class="wordmark">${e(ui.siteName)}</span></a>
215215
<nav>
216216
${nav}
217217
<a class="navlink gh" href="${REPO}" rel="noopener" target="_blank">

‎bin/pages/render-page.mjs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,12 @@ ${jsonLd}
202202
</svg>
203203
204204
<header class="bar">
205-
<a class="brand" href="${L.home}"><span class="logo">D</span>${ui.siteName}</a>
205+
<a class="brand" href="${L.home}"><span class="logo">D</span><span class="wordmark">${ui.siteName}</span></a>
206206
<nav>
207-
${langMenu(locale, translations, ui, (l) => routeFor(l, page.slug))}
208207
<a href="${REPO}" rel="noopener" target="_blank">
209208
<svg class="ghmark" aria-hidden="true"><use href="#gh-mark"></use></svg> GitHub
210209
</a>
210+
${langMenu(locale, translations, ui, (l) => routeFor(l, page.slug))}
211211
</nav>
212212
</header>
213213
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# 顶栏四件事:一行里的高度、顺序、手机取舍(2026-09-02)
2+
3+
## 起因
4+
5+
用户截图:顶栏里 hover 到 **GitHub** 和 hover 到 **English**,两个填充块高度不一样。
6+
7+
## 1. 桌面端:39px vs 31px
8+
9+
量出来(`edit.chaxus.com`,1512px):
10+
11+
| 元素 | 高度 | line-height |
12+
| --------------------------- | ------- | ----------- |
13+
| `header.bar nav a` (GitHub) | 39.09px | 23.1px |
14+
| `.lang-trigger` (English) | 31px | 14px |
15+
16+
两者的 padding 完全一样(`8px 12px`),差的是行盒:
17+
18+
- 导航链接**没写** `line-height`,继承 body 的正文行距 `1.65` → 14 × 1.65 = 23.1px;
19+
- 语言触发器写了 `line-height: 1`,而它里面最高的是 15px 的地球图标 → 15px。
20+
21+
39.09 − 31 = 8.09px,正是 23.1 − 15。
22+
23+
`docs/explorations/2026-08-26-language-menu-disclosure.md` 里明确写着这个触发器的设计
24+
意图是"长得和旁边的 GitHub 链接一模一样"——所以这是对既定意图的回归,不是取舍。
25+
26+
**修**:两处都显式写 `line-height: 22px`(`landing.css` 与 `home.css` 各一份,顶栏本来
27+
就有两份实现)。22 不是新数字,是 `.ran-btn-content` 的默认行高,本文件里已经在用;
28+
22 + 8×2 = 38px,正好等于 `/history` 顶栏里那个 `r-theme-switch` 药丸的高度,三件东西
29+
就都是 38 了。顶栏总高 71px 不变(39.09 + 32 本来也是四舍五入到 71)。
30+
31+
## 2. 手机端:同一个 bug,方向相反
32+
33+
`@media (max-width: 620px)` 会把 `.lang-current`(语言名)藏掉,只剩地球和箭头。文本行
34+
盒随之消失,触发器又掉回 31px,而 GitHub 还是 38px——桌面修好,手机照旧。
35+
36+
**修**:`min-height: calc(22px + var(--ran-space-2) * 2)`,从下面顶住,与 padding token
37+
联动而不是手抄 38。
38+
39+
## 3. 顺序:主页和别的页是反的
40+
41+
| 页面 | 顶栏顺序 |
42+
| ---------------------------------- | ------------------------------------ |
43+
| `/`(`render-home.mjs`) | Offline · No sign-up · GitHub · 语言 |
44+
| `/help` `/about` `/404` `/history` | **语言 · GitHub**(· 主题) |
45+
46+
同一个站,从主页走到 `/help`,语言开关就跳到行的另一头。统一成主页那一版:外链在前,
47+
偏好类控件(语言、主题)收尾。改了 `render-page.mjs`、`public/404.html`、`history.html`。
48+
49+
## 4. 手机上顶栏放不下,两个页面横向溢出
50+
51+
`/history` 与 `/embed-demo` 是仅有的两个"应用面"页面:它们没有页脚,于是把主题开关放进了
52+
顶栏,一行里有三个控件。390px 下实测:
53+
54+
| 页面 | 横向溢出 | 现象 |
55+
| ------------------ | -------- | ------------------------------- |
56+
| `/history` | +17px | 品牌名折成两行 |
57+
| `/embed-demo.html` | +27px | "Embed API" 折成两行(60px 高) |
58+
59+
`mobile-overflow.spec.ts` 按 sitemap 遍历,而这两页一个 noindex 一个是 demo,都不在
60+
sitemap 里——所以站点唯一的手机溢出门禁从来没看过它们。
61+
62+
算过几种取法(390px,顶栏左右各 20px gutter):
63+
64+
| 方案 | `/history` | `/embed-demo` |
65+
| ------------------------ | --------------- | ------------------------- |
66+
| 现状 | 407 ✗ | 417 ✗ |
67+
| 藏 GitHub | 382 ✓(余 8px) | 408 ✗ |
68+
| 藏 GitHub + 藏页内链接 | — | 319 ✓(但两个链接都没了) |
69+
| **品牌只留标记,去掉字** | **340 ✓** | **366 ✓** |
70+
71+
最后一种最省事也最不丢信息:24px 的方块标记仍然是回首页的链接、仍然写着站名的首字母,
72+
而 137px 的字号 16 品牌名是这一行唯一付不起的东西(Apple / GitHub / Stripe 的手机顶栏
73+
都是这么做的)。代价是要给品牌名包一个 `<span class="wordmark">`——原来它是裸文本节点,
74+
CSS 根本选不中。五处 chrome 各加一次(两个生成器 + 404 + history + embed-demo),
75+
`@media (max-width: 620px)` 里一行 `display: none`。
76+
77+
顺带清掉一条过期规则:`home.css` 在 620px 以下把 GitHub 链接藏了,注释说是"为了给宽到
78+
能放下 Português 的语言触发器腾地方"——而触发器早就在手机上只剩图标了(landing.css 那份
79+
注释里已经写了"GitHub 现在可以留下")。主页手机顶栏因此比别的页少一个链接。删掉。
80+
81+
## 5. 顺带:`/history` 工具栏 31px vs 32px
82+
83+
`.history-filter` 药丸 31px,旁边的 `r-input` 搜索框 32px,两者在同一行差半个像素。
84+
`min-height: 32px`。
85+
86+
## 用例
87+
88+
`test/e2e/language-menu.spec.ts` 的 `page chrome` 组新增两条:
89+
90+
- `{desktop, phone} × {/, /zh-CN/, /help, /history, /embed-demo.html}`:顶栏里每一件
91+
可见控件的 `height@top` 必须全部相同(正则 `^(\S+)( \1)*$` 直接判"这些字符串是不是同
92+
一个")。量渲染结果而不是比 CSS 声明,因为顶栏有两份实现,两边都可能坏。
93+
- `the app surfaces fit a phone too`:`/history` 与 `/embed-demo.html` 在 390px 下
94+
`scrollWidth - clientWidth <= 1`。补上 sitemap 门禁够不到的那两页。
95+
96+
反向验证(三条修复各撤一次,用例都变红):
97+
98+
| 撤掉 | 变红的用例 |
99+
| ---------------------------- | ------------------------------------------------------------- |
100+
| `line-height: 22px` | desktop 那条(`/` 报 items differ) |
101+
| `min-height: calc(...)` | phone 那条(`/` 报 items differ) |
102+
| `.wordmark { display:none }` | phone 那条(`/embed-demo`)+ 手机溢出那条(`/history` +17px) |
103+
104+
全量:单测 3410 通过,E2E 159 通过 + `@serial` 2 通过。

‎history.html‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@
4949
</svg>
5050

5151
<header class="bar">
52-
<a class="brand" href="/"><span class="logo">D</span>Document Editor</a>
52+
<a class="brand" href="/"><span class="logo">D</span><span class="wordmark">Document Editor</span></a>
5353
<nav>
54+
<a class="gh" href="https://github.com/ranuts/document" rel="noopener" target="_blank">
55+
<svg class="ghmark" aria-hidden="true"><use href="#gh-mark"></use></svg> GitHub
56+
</a>
5457
<!-- Every target is this page; the locale rides in the query, which is
5558
what the app's i18n reads. -->
5659
<r-popover class="lang-menu" placement="bottom" trigger="click" role="button" aria-label="Language">
@@ -90,9 +93,6 @@
9093
</div>
9194
</r-content>
9295
</r-popover>
93-
<a href="https://github.com/ranuts/document" rel="noopener" target="_blank">
94-
<svg class="ghmark" aria-hidden="true"><use href="#gh-mark"></use></svg> GitHub
95-
</a>
9696
<r-theme-switch class="theme-switch" label="Theme"></r-theme-switch>
9797
</nav>
9898
</header>

‎index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@
262262
<section id="landing-hero">
263263
<header class="bar">
264264
<div class="wrap">
265-
<a class="brand" href="/"><span class="logo">D</span>Document Editor</a>
265+
<a class="brand" href="/"><span class="logo">D</span><span class="wordmark">Document Editor</span></a>
266266
<nav>
267267
<a class="navlink" href="/offline-document-editor">Offline</a>
268268
<a class="navlink" href="/no-signup-document-editor">No sign-up</a>

‎public/404.html‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,11 @@
124124
</svg>
125125

126126
<header class="bar">
127-
<a class="brand" href="/"><span class="logo">D</span>Document Editor</a>
127+
<a class="brand" href="/"><span class="logo">D</span><span class="wordmark">Document Editor</span></a>
128128
<nav>
129+
<a href="https://github.com/ranuts/document" rel="noopener" target="_blank">
130+
<svg class="ghmark" aria-hidden="true"><use href="#gh-mark"></use></svg> GitHub
131+
</a>
129132
<r-popover class="lang-menu" placement="bottom" trigger="click" role="button" aria-label="Language">
130133
<span class="lang-trigger">
131134
<svg class="langmark" aria-hidden="true" viewBox="0 0 16 16">
@@ -161,9 +164,6 @@
161164
</div>
162165
</r-content>
163166
</r-popover>
164-
<a href="https://github.com/ranuts/document" rel="noopener" target="_blank">
165-
<svg class="ghmark" aria-hidden="true"><use href="#gh-mark"></use></svg> GitHub
166-
</a>
167167
</nav>
168168
</header>
169169

‎public/embed-demo.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@
219219
</svg>
220220

221221
<header class="bar">
222-
<a class="brand" href="/"><span class="logo">D</span>Document Editor</a>
222+
<a class="brand" href="/"><span class="logo">D</span><span class="wordmark">Document Editor</span></a>
223223
<nav>
224224
<a href="/embed-document-editor">Embed API</a>
225225
<a href="https://github.com/ranuts/document" rel="noopener" target="_blank">

‎public/home.css‎

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,11 @@ body {
149149
padding: var(--ran-space-2) var(--ran-space-3);
150150
border-radius: var(--ran-radius-sm);
151151
font-size: 14px;
152-
line-height: 1;
152+
/* Same 22px as the nav links beside it -- see #landing-hero .bar nav .navlink.
153+
On a phone the label is hidden and only the two icons are left, so the line
154+
box no longer sets the height: hold it from below instead. */
155+
line-height: 22px;
156+
min-height: calc(22px + var(--ran-space-2) * 2);
153157
color: var(--ran-color-text-secondary);
154158
cursor: pointer;
155159
transition: 0.15s ease;
@@ -244,6 +248,11 @@ body {
244248
#landing-hero .lang-current {
245249
display: none;
246250
}
251+
/* Phone: the mark stays, the wordmark goes -- see landing.css, which does the
252+
same for every other page's copy of this bar. */
253+
#landing-hero .wordmark {
254+
display: none;
255+
}
247256
}
248257

249258
/* ---------- top bar ---------- */
@@ -290,6 +299,11 @@ body {
290299
padding: var(--ran-space-2) var(--ran-space-3);
291300
border-radius: var(--ran-radius-sm);
292301
font-size: 14px;
302+
/* One height for every item in the bar. Without this the links inherit the
303+
body's prose leading (1.65 -> 23.1px) while the language trigger sets its
304+
own line-height: the two hover pills came out 39px and 31px, visibly
305+
different boxes in one row. 22px matches the theme switch beside them. */
306+
line-height: 22px;
293307
color: var(--ran-color-text-secondary);
294308
transition: 0.15s ease;
295309
}
@@ -1111,16 +1125,6 @@ body {
11111125
display: none;
11121126
}
11131127
}
1114-
@media (max-width: 620px) {
1115-
/* Phone: the bar is brand + GitHub + a language name, and at 390px the
1116-
language trigger (wide enough for "Português") pushed the caret off the
1117-
viewport and broke the brand onto two lines. GitHub loses: it is one line
1118-
down in the footer of every page, while the language switch is the only
1119-
way to change the language. */
1120-
#landing-hero .bar nav .navlink.gh {
1121-
display: none;
1122-
}
1123-
}
11241128

11251129
@media (max-width: 560px) {
11261130
#landing-hero .dw-body {

‎public/landing.css‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ header.bar nav a {
7676
padding: var(--ran-space-2) var(--ran-space-3);
7777
border-radius: var(--ran-radius-sm);
7878
font-size: 14px;
79+
/* One height for every item in the bar. Without this the links inherit the
80+
body's prose leading (1.65 -> 23.1px) while the language trigger sets its
81+
own line-height: the two hover pills came out 39px and 31px, visibly
82+
different boxes in one row. 22px matches the theme switch beside them. */
83+
line-height: 22px;
7984
color: var(--ran-color-text-secondary);
8085
text-decoration: none;
8186
transition: 0.15s ease;
@@ -112,7 +117,12 @@ header.bar nav a:hover {
112117
padding: var(--ran-space-2) var(--ran-space-3);
113118
border-radius: var(--ran-radius-sm);
114119
font-size: 14px;
115-
line-height: 1;
120+
/* Same 22px as the nav links beside it -- see header.bar nav a. On a phone
121+
the label is hidden and only the two icons are left, so the line box no
122+
longer sets the height: hold it from below instead, or the pill shrinks to
123+
31px next to a 38px GitHub link. */
124+
line-height: 22px;
125+
min-height: calc(22px + var(--ran-space-2) * 2);
116126
color: var(--ran-color-text-secondary);
117127
cursor: pointer;
118128
transition: 0.15s ease;
@@ -219,6 +229,16 @@ header.bar nav a:hover {
219229
.lang-current {
220230
display: none;
221231
}
232+
/* Phone: the bar keeps the mark and drops the wordmark. The two app surfaces
233+
(/history, /embed-demo) put a third control in this row -- a theme switch,
234+
which every other page keeps in a footer they do not have -- and at 390px
235+
brand + links + switch ran 17px and 27px past the viewport: the whole page
236+
scrolled sideways and a nav label broke onto two lines. The mark is the
237+
same link home and still names the site; 137px of wordmark is what the row
238+
could not afford. */
239+
header.bar .wordmark {
240+
display: none;
241+
}
222242
}
223243

224244
/* ---------- article column ---------- */

0 commit comments

Comments
 (0)