Skip to content

fix(web-ui): center CJK text and the device mark on glyph ink - #3243

Merged
kev1n77 merged 1 commit into
GCWing:mainfrom
kev1n77:fmy/ui-main
Sep 28, 2026
Merged

kev1n77 merged 1 commit into
GCWing:mainfrom
kev1n77:fmy/ui-main

Conversation

@kev1n77

@kev1n77 kev1n77 commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fixes: none — there is no corresponding upstream issue; this is a self-contained vertical-alignment fix found while inspecting the web UI.

This PR fixes two classes of vertical centering problems in the web UI. First, CJK text sat visibly low inside its own line box: the bundled OpenBitFun HarmonyOS Sans SC profile declared no font metric overrides, so the browser split the line box using the font's own ascent (92.8%) and descent (24.4%), while Han glyph ink only occupies roughly 84.5% above and 7.5% below the baseline — leaving about 0.043em of extra empty space under every line of Chinese text. Selected paragraphs in the flow chat, sent message bubbles, and any mixed CJK/Latin run inherited that offset. The fix adds ascent-override: 97.1% and descent-override: 20.1% to that @font-face, which realigns the line box with the actual ink. Second, the device mark in the navbar footer carried a hard-coded transform: translateY(1px) nudge that, once measured against the label's ink center, overshot and pushed the icon below the text baseline; that nudge is removed and the icon is centered by the flex line box like any other glyph.

Type and Areas

Type: bug fix (UI/UX).

Areas: web UI (frontend font profile and navigation panel styles).

Motivation / Impact

Previously, users saw text that was not vertically centered in several high-traffic places. Measured with an 8x device-pixel ink probe on the real DOM, before and after this change:

Case Before After
Selected CJK line in flow chat (14px / 1.62 line-height) — top vs bottom padding difference 1.13px 0.13px
Navbar footer device mark vs label ink center mark 1.31px low mark 0.31px low
Sent message bubble (13px / 1.5, mixed $MFT 是什么文件?) -0.19px +0.31px

The remaining sub-pixel deltas are below one device pixel at 1x scaling and come from hinting, not from the metric split. Impact is limited to rendering: no markup, API, persisted shape, or protocol changes, so there is no upgrade or cross-version concern. Because the override is scoped to the bundled HarmonyOS profile, systems that fall back to another font are unaffected.

Verification

Commands run and their outcomes:

  • node --test scripts/web-font-profile.test.mjs — 7/7 passing.
  • node --test scripts/audit-typography-tokens.test.mjs — 15/15 passing.
  • node scripts/audit-typography-tokens.mjs — zero violations.
  • pnpm exec vitest run src/app/components/NavPanel (from src/web-ui) — 34 files, 204 tests passing.

Manual checks: the three before/after measurements in the table above were produced by a local probe page that renders the production font profile and the real component markup at 8x device pixel ratio, comparing the ink bounding box against the line box.

Not verified in this PR: the full pnpm run check:web gate was started but not completed, so it is not claimed as green; end-to-end and visual snapshot suites, macOS rendering, and the remote scenarios (remote workspace, remote control, Peer Device Mode, Detached Dispatch) were not exercised. No persisted shape, command surface, or remote-facing behavior changed, so remote-scenario risk is limited to rendering, but the rendering path itself was only verified locally on Windows.

Reviewer Notes

AI assistance: this change was authored with AI assistance, and the human author reviewed and ran the checks listed above. Test level: unit and static token audits, plus a local visual ink probe; no e2e, device matrix, or cross-platform visual baseline.

Screenshots (required for UI changes): the three captures below were taken on the fix build. They are current-state only — no before-state captures are attached, so the before/after comparison for these surfaces rests on the probe numbers in the table above. The images live on the author's fork branch fmy/pr-3243-assets so that they can be embedded here without adding binary files to the PR diff.

Navbar footer device row — the device mark and its label now share one ink center instead of the mark sitting 1.31px low:

Navbar footer device row after the fix

Flow chat — a selected Chinese run in a paragraph, with the selection toolbar open; the selection highlight no longer leaves more space below the glyphs than above:

Selected Chinese paragraph in the flow chat after the fix

Sent message bubble with Chinese text — the text now sits centered in the bubble:

Sent Chinese message bubble after the fix

Rollback is a two-file revert with no data or configuration migration.

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable.

Generated with OpenBitFun

A line box is split by a font's ascent and descent, not by the glyphs drawn in
it. HarmonyOS Sans declares 92.8% / 24.4%, while its ideographs draw from 84.5%
above the baseline to 7.5% below it, so a Chinese line box kept about 0.043em
more room under its glyphs than over them: a selected line read as an uneven
band (1.13px more space below than above at 14px) and message text sat high in
its bubble.

Split the same 117.2% as 97.1% / 20.1% on the SC face only, which moves the
shared baseline down by exactly that 0.043em before the glyphs are painted. The
sum is what `line-height: normal` and `1lh` resolve to, and the product sets an
explicit numeric leading on every other text it lays out, so no laid out box
changes size. The Latin-first base face, the code face, and the zh-TW system
stack keep their own metrics.

The nav panel footer pushed its device mark down a pixel to follow that text,
but the marks that reach this row state their own `opticalShift` as 0, so the
nudge left the mark 1.31px below the label's ink centre instead of 0.31px.
Remove it and record the measurement in the comment.

Measured at 8x device pixels: the selected-line gap difference drops from 1.13px
to 0.13px, and the device mark from 1.31px to 0.31px below its label.

Verified with the NavPanel suite (34 files, 204 tests), the web font profile
guard (7 tests), and the typography token audit (15 tests plus a zero-violation
audit run).

Co-authored-by: OpenBitFun <318544290+bitfun-ai@users.noreply.github.com>
@kev1n77
kev1n77 marked this pull request as ready for review September 28, 2026 09:34
@kev1n77
kev1n77 merged commit 90e6308 into GCWing:main Sep 28, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant