fix: navigation labels wrapped mid-word at the largest font scale

At font_scale 2.0 the bottom navigation read "Calenda / r" and "Setting / s".
NavigationBarItem's label had no maxLines, so Compose wrapped it rather than
truncating, breaking a word across two lines in a 4-item tab bar.

maxLines = 1 with an ellipsis degrades to "Calen…" instead — still recognisable,
and the icon above it carries the meaning regardless.

FOUND BY DOING THE THING NOBODY HAD DONE

Font scaling was a standing QA gap: written down, never run. Driven at 1.3 and
2.0 on PeriodMinSdk26, through onboarding to Today.

Everything else held. The 72sp hero survives 2.0, Today scrolls so nothing below
the fold is lost, and every onboarding step keeps its primary button reachable —
including the two that carry three buttons or three option cards beneath an
illustration, which is why their art is 104dp where the rest take 120-128dp.
That sizing was guessed when the artwork landed and is now checked.

This defect is older than the artwork work and unrelated to it; the font-scale
pass is simply the first thing that looked.

Recorded in docs/qa/ClaudeQACoverage.md, where the gap it closes was listed.
Still unreached: font scaling in dark mode, and on anything other than a phone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
null 2026-08-18 20:34:38 -05:00
parent 5fc94536fe
commit 928680a61a
2 changed files with 28 additions and 3 deletions

View File

@ -17,6 +17,7 @@ import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
@ -107,7 +108,21 @@ fun PeriodApp() {
}
},
icon = { Icon(destination.icon, contentDescription = null) },
label = { Text(stringResource(destination.labelRes)) },
// maxLines and ellipsis, because at the largest
// accessibility font scale these labels do not fit and
// Compose's default is to wrap them mid-word: the tab
// bar reads "Calenda / r" and "Setting / s". Found by
// setting font_scale to 2.0 on a device, which nothing
// in the build does. Ellipsis degrades to "Calend…",
// which is still a word somebody can recognise, and the
// icon above it carries the meaning anyway.
label = {
Text(
stringResource(destination.labelRes),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
)
}
}

View File

@ -153,8 +153,18 @@ existing is not a failure; it not existing while the gaps do is.
were checked by reading the view hierarchy, which proves they exist and not
that they make sense in sequence. Pass G is not complete until somebody
navigates a screen with their eyes shut.
- **Font scaling untried.** The hero number is 72sp; at the largest accessibility
scale it may not fit beside anything.
- **~~Font scaling untried~~ — done on 2026-08-18, and it found one defect.**
Driven at `font_scale` 1.3 and 2.0 on `PeriodMinSdk26`, through onboarding to
Today. The hero number survives: at 2.0 the "14" and its labels still fit, and
Today scrolls so nothing below is lost. Every onboarding step survives too,
including the two carrying three buttons or three option cards under an
illustration — their art is deliberately 104 dp where the others take 120128.
**The bottom navigation bar did not.** With no `maxLines`, Compose wrapped the
labels mid-word at 2.0: the tab bar read *"Calenda / r"* and *"Setting / s"*.
Fixed in `PeriodApp.kt` with `maxLines = 1` and an ellipsis, which degrades to
"Calen…" — still recognisable, and the icon above carries the meaning. What is
still unreached: font scaling has only been driven in light mode, and only on
a phone-sized screen.
- **~~No device at `minSdk`~~ — partly closed on 2026-08-18 at `0d280d5`.** The
app has now been built, installed and driven on `PeriodMinSdk26`, an API 26
emulator: onboarding start to first forecast, the Material 3 date picker,