Floor lineHeightXSmall at 11 so small device font scales don't clip descenders and link underlines - #100448
Floor lineHeightXSmall at 11 so small device font scales don't clip descenders and link underlines#100448MelvinBot wants to merge 1 commit into
Conversation
…rs and underlines Co-authored-by: mkhutornyi <mkhutornyi@users.noreply.github.com>
|
🤖 Android test steps verification results: ✅ pass On standalone Android NewDot with font_scale=0.85 (minimum) and high contrast enabled, the sign-in fine-print line renders the Terms of Service and Privacy links fully underlined and shows no clipped descenders (the
No JS console errors were observed. Font scale was restored to 1.0 after the run. Reaching Home required completing a one-time onboarding flow for the freshly-provisioned test account — that was navigation only, not part of the test. |
|
🤖 Web test steps verification results: On web the sign-in fine print renders intact — no clipped descenders — but the underline assertion could not be exercised, because the high-contrast toggle would not flip on the web session and underlines are high-contrast-only by design. Note the documented steps are Android-specific (minimum device font size), and this fix is a no-op at font scale 1, which is always the case on web, so this run is only a regression check. Underline gating referenced above: The Android run — the platform this bug actually reproduces on — passed all six steps end to end, including the high-contrast underline check at minimum font scale: see the Android results. view run · no recording available |
DetailsExplanation of ChangeFixed Issues$ #97409 Precondition:Device is Android 16. Tests
Offline testsSame as Tests QA StepsSame as Tests
PR Author Checklist
@MelvinBot please set the PR body to the content in the details section above |
|
🤖 PR body updated to the content you provided, verbatim. Two things dropped out with the replacement, in case they weren't intended:
Say the word if you want either restored. |
|
@MelvinBot restore your previous Explanation of Change and mark as reay for review |
|
@Pujan92 @mkhutornyi One of you needs to copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
|
🤖 Done — the Explanation of Change is restored and the PR is out of draft, marked ready for review. Everything else in the body you supplied is untouched. The Screenshots/Videos section is still absent (you didn't ask for it back) — say the word if you want the Android and MacOS evidence restored too. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppandroid.movAndroid: mWeb ChromeiOS: HybridAppios.moviOS: mWeb SafariMacOS: Chrome / Safariweb.mov |
|
We did not find an internal engineer to review this PR, trying to assign a random engineer to #97409 as well as to this PR... Please reach out for help on Slack if no one gets assigned! |












Explanation of Change
fontSizeExtraSmallis a fixed9, butlineHeightXSmallwasgetValueUsingPixelRatio(11, 17), which scales down with the device font scale. At Android's minimum font size setting (PixelRatio.getFontScale()≈ 0.8–0.85) that producesfontSize: 9with a line height of ~8.8–9.4 — below Expensify Neue's natural line height (~1.18em, so ~10.6 at size 9). Android'sCustomLineHeightSpanthen clamps the descent, which clips everything that renders below the baseline: the descenders (y,g) and the underline on links. iOS and web don't clamp glyphs this way, which is why the report is Android-only.This affects
styles.textExtraSmallSupporting, whichmuted-text-xsmaps to inBaseHTMLEngineProvider, and whichAnchorRendereruses for links inside it — i.e. the sign-in "By logging in, you agree to the Terms of Service and Privacy." string.The fix floors the value at 11, so the line height can never drop below the font's natural line height:
This is a no-op at font scale ≥ 1 (the default), so there is no behavior change for users who haven't shrunk their device font size.
AI tests run locally
npm run lint-changed— passnpm run typecheck— passnpm run spell-changed— passnpm run gh-actions-unused-styles— pass (no unused styles)npm run test -- tests/unit/TextVariantTest.tsx tests/unit/ButtonStyleUtilsTest.ts tests/unit/ReceiptUtilsTest.ts tests/ui/components/MoneyRequestReceiptViewTest.tsx— 46 tests passnpm run prettierwere not run: the repo has noprettiernpm script, and formatting on the changed file is unaffected (indentation and line width match the surrounding lines).Fixed Issues
$ #97409
PROPOSAL: #97409 (comment)
Precondition:
Device is Android 16.
Device font size is minimum.
Tests
Offline tests
Same as Tests
QA Steps
Same as Tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)Avatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.