fix(android): visual polish from the web design canon (#128) #159

Merged
nalum merged 3 commits from fix/android-visual-polish into main 2026-08-18 16:45:06 +00:00
Owner

Closes #128. The Android visual divergences from the parity report's section 4, in three commits, stacked on #158.

The save arc (form grammar rule 10). AppSaveButton now carries the web SaveButton arc: the spinner joins the unchanged label while saving, success shows the tick inside a celebrate ring for a beat before the sheet closes (SaveArcState mirrors useSaveArc, 650 ms hold). Adopted at the form primaries (profile save, job sheet Save changes, reward edit, meal day plan, list rename, Take this job, Claim it). Every label-swapping busy button ("Saving…", "Deleting…", "Taking…", "Claiming…", "Unlinking…") keeps its name now and simply disables while busy. Under reduced motion the spinner holds still; the arc still reads.

Loading skeletons and the themed status line. BoardSkeleton is the web LoadingBoard — the page's fetching line over grey pulsing shapes — shown only while the first cache fill runs and the cache is empty, so a genuinely empty board keeps its invitation. Adopted on Jobs ("Fetching the chore list…"), Lists and the list detail. The menu board's raw android.widget.Toast is gone: a themed in-app ToastLayer (card dress, accent edge, pinned above the navigation, 4 s hold) carries "Added N to the list" in both shells.

Dress details. Page headings rise to headlineLarge (the web's 34px h1, Today's greeting included); the error banner's detail line goes quiet — small, monospace, ink-soft — while the headline alone keeps the danger voice (the web's ErrorDetail); cards throw a deeper shadow in dark mode; the mark fitting room's Cancel wears the .btn-quiet dress (new AppQuietButton, 2dp line border); the theme picker groups its families under the web's three group headings with one accent dot per chip; and the system-bar icon polarity follows the in-app mode, not the OS.

Deliberately not taken (rule 1, recorded here and in the commit): sheets stay bottom sheets on every width — the native idiom on this surface — rather than becoming the web's centred ≥700px card; the splash keeps the Hearth default because it draws before any preference can load; the remaining minor metrics (header date size, card padding, mark disc, stamp shadow, tab label size) stay native.

Verified on the emulator against the live deploy: theme picker shows all three group headings with single-dot chips; the ingredients push lands as an in-app themed toast (TextView inside the app's own hierarchy, not a system toast window); profile rename saved through the arc and closed after the hold; offline meal edit still queues and flushes. make check green; Android unit tests green.

🤖 Generated with Claude Code

Closes #128. The Android visual divergences from the parity report's section 4, in three commits, stacked on #158. **The save arc (form grammar rule 10).** `AppSaveButton` now carries the web `SaveButton` arc: the spinner joins the unchanged label while saving, success shows the tick inside a celebrate ring for a beat before the sheet closes (`SaveArcState` mirrors `useSaveArc`, 650 ms hold). Adopted at the form primaries (profile save, job sheet Save changes, reward edit, meal day plan, list rename, Take this job, Claim it). Every label-swapping busy button ("Saving…", "Deleting…", "Taking…", "Claiming…", "Unlinking…") keeps its name now and simply disables while busy. Under reduced motion the spinner holds still; the arc still reads. **Loading skeletons and the themed status line.** `BoardSkeleton` is the web `LoadingBoard` — the page's fetching line over grey pulsing shapes — shown only while the first cache fill runs and the cache is empty, so a genuinely empty board keeps its invitation. Adopted on Jobs ("Fetching the chore list…"), Lists and the list detail. The menu board's raw `android.widget.Toast` is gone: a themed in-app `ToastLayer` (card dress, accent edge, pinned above the navigation, 4 s hold) carries "Added N to the list" in both shells. **Dress details.** Page headings rise to `headlineLarge` (the web's 34px h1, Today's greeting included); the error banner's detail line goes quiet — small, monospace, ink-soft — while the headline alone keeps the danger voice (the web's `ErrorDetail`); cards throw a deeper shadow in dark mode; the mark fitting room's Cancel wears the `.btn-quiet` dress (new `AppQuietButton`, 2dp line border); the theme picker groups its families under the web's three group headings with one accent dot per chip; and the system-bar icon polarity follows the in-app mode, not the OS. **Deliberately not taken (rule 1, recorded here and in the commit):** sheets stay bottom sheets on every width — the native idiom on this surface — rather than becoming the web's centred ≥700px card; the splash keeps the Hearth default because it draws before any preference can load; the remaining minor metrics (header date size, card padding, mark disc, stamp shadow, tab label size) stay native. Verified on the emulator against the live deploy: theme picker shows all three group headings with single-dot chips; the ingredients push lands as an in-app themed toast (`TextView` inside the app's own hierarchy, not a system toast window); profile rename saved through the arc and closed after the hold; offline meal edit still queues and flushes. `make check` green; Android unit tests green. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The web's form grammar rule 10: the primary button carries the whole
saving arc — the spinner joins the label (the name never changes), and
success shows the tick with a celebrate ring before the sheet closes.
Android's busy buttons swapped the label for a progress word instead,
the exact pattern the rule forbids. AppSaveButton now renders the arc
(spinner beside the unchanged label, then ✓ inside a celebrate ring)
and the form primaries adopt it; the label-swapping delete verbs keep
their name and simply disable while busy.
The boards showed nothing at all while the first cache fill ran — the
'Fetching…' strings sat unused in the catalog — and the menu board
announced its one status through a raw android.widget.Toast outside the
theme. A shared BoardSkeleton now holds the fetching line while a
screen's cache is empty and loading, and the toast becomes the same
quiet themed status line the other boards use.
fix(android): dress details from the web design canon
All checks were successful
check / commits (pull_request) Successful in 7s
check / go (pull_request) Successful in 3m26s
check / report (pull_request) Successful in 3s
check / web (pull_request) Successful in 3m27s
android / build (pull_request) Successful in 11m28s
android / report (pull_request) Successful in 3s
check / commits (push) Successful in 8s
check / go (push) Successful in 3m1s
check / report (push) Has been skipped
check / web (push) Successful in 3m23s
android / build (push) Successful in 13m26s
android / report (push) Has been skipped
tag / tag (push) Successful in 12m57s
release / binaries (push) Successful in 2m49s
release / docs (push) Successful in 3m43s
release / image (push) Successful in 5m16s
release / android (push) Successful in 9m31s
release / manifests (push) Successful in 1m42s
release / module (push) Successful in 1m8s
release / release (push) Successful in 17s
5f491804f6
The smaller visual divergences from the parity report, batched: page
headings rise to headlineLarge (the web's 34px h1); the error banner's
detail line goes quiet — small, monospace, ink-soft — while the
headline keeps the danger voice (the web's ErrorDetail); cards throw a
deeper shadow in dark mode; the mark fitting room's Cancel wears the
web's .btn-quiet dress (new AppQuietButton, 2dp line border); the
theme picker groups its families under the web's group headings with
one accent dot per chip; and the system-bar icon polarity follows the
in-app mode rather than the OS.

Deliberately not taken (recorded per rule 1): sheets stay bottom
sheets on every width — the native idiom on this surface — rather than
becoming the web's centred >=700px card; the splash keeps the Hearth
default because it draws before any preference can load; the remaining
minor metrics (header date size, card padding, mark disc, stamp
shadow, tab label size) stay native.

Test report

Suite Tests Result Skipped
Unit 1370 ✅ pass 1
Integration 87 ✅ pass —

Coverage: 27.2%

Updated by the check workflow · commit 5f491804f6

<!-- ci-test-report --> ## Test report | Suite | Tests | Result | Skipped | | --- | --: | --- | --: | | Unit | 1370 | ✅ pass | 1 | | Integration | 87 | ✅ pass | — | **Coverage:** 27.2% <sub>Updated by the check workflow · commit 5f491804f6a87ab47c68b00208e4f0972dd1bb3c</sub>

Android test report

Suite Tests Result Skipped
Unit (debug) 31 ✅ pass 0

Coverage: 2.4% of lines

Updated by the android workflow · commit 5f491804f6

<!-- android-test-report --> ## Android test report | Suite | Tests | Result | Skipped | | --- | --: | --- | --: | | Unit (debug) | 31 | ✅ pass | 0 | **Coverage:** 2.4% of lines <sub>Updated by the android workflow · commit 5f491804f6a87ab47c68b00208e4f0972dd1bb3c</sub>
nalum changed target branch from feat/calendar-marks to main 2026-08-18 16:44:59 +00:00
nalum merged commit 5f491804f6 into main 2026-08-18 16:45:06 +00:00
nalum deleted branch fix/android-visual-polish 2026-08-18 16:45:06 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
eagraiclainne/app!159
No description provided.