Mobile redesign: one-scroll dashboard, a header that fits, five real tabs - #225
Merged
Conversation
…page The dashboard used to hold four independently scrolling panels, so a phone gave you four small windows into four lists and no way to see the page. Every section is now capped and the PAGE scrolls, which is the only scroll a phone should have. Assets gets its own screen behind View all, with search and sort, because a five-row preview is a summary and not somewhere you can find a token. GNUS is pinned first everywhere it is listed. That rule existed and phase 25 had quietly demoted it to a tie-break, so a funded wallet could bury its own native token under whatever happened to be worth more that morning. It now lives in one comparator that both the panel and the page call, so the two cannot disagree. The Assets panel header goes back to the shared section-title component: it was the one panel drawing its own, and on a phone that read as a different kind of thing sitting among Compute, Markets and Transactions. Panel rhythm is symmetric - the gap above a section title now equals the gap below it. The component's own doc claimed it already did this; it did not, and the claim is corrected rather than left to mislead the next reader.
The wallet control used to take 224px of a 342px header - more than half the bar for one control - because it absorbed whatever the brand lockup left. It is now a 44px icon beside a 44px menu button: a fixed 100px cluster, so the header stops being a tug of war and the brand keeps its size at every text scale. Neither control carries a border. In this palette a fill cannot identify a control at all - surfaceMenu on the bar measures 1.11:1 - so the glyphs do the identifying, at 7.54:1 and 19.29:1, which is better than the 3.30:1 edge they replace. The bottom bar becomes Home, Assets, Swap, Activity, News. More leaves it, and the menu button ships in the SAME change rather than after it: removing More first would have stranded Markets, Web, Feedback and Settings with no way back on a phone. Assets is reachable from the bar as well as from the dashboard link, and both entrances now behave the same way rather than one stacking a page. Known and deliberate: with the wallet name gone, the avatar draws a currency icon, so two ETH wallets render the same header. The semantic label still names the wallet and the chain, so this is a sighted-user gap rather than a total one. Filed as a todo with the monogram that fixes it.
A transaction row used to print its action in a chip beside the token. On a phone that chip was 44.5px, too narrow for six of the eight words it could hold, so it clipped the one thing it existed to show. The action now leads the subtitle, where the line is long enough for it. Lead and context are separated by COLOUR rather than by weight or a separator - textPrimary against textSecondary, 19.4:1 against 6.01:1. That was the only separation available for zero width, and width is the entire constraint on that line. One weight step at 13px was tried on device and read as a single run of text. The job hash is gone from the subtitle. It identified nothing anyone could act on and it was eating the room the wording needed. Counterparty addresses stay on send and receive rows, where they do identify something. Status moves to a capped tail on the narrow row, and only there: the wide page already states it in a pill, and printing it twice is worse than either. Merged with develop's phone-width work rather than over it - the smaller title, subtitle and gaps it introduced are all preserved here, and the filter bar keeps the 44pt touch targets that change gave it.
A drawer footer added the phone's full home-indicator inset on top of its own padding, so on an iPhone the button sat 54pt off the bottom of the sheet with nothing in the gap. It now caps that inset, which lands it at 40 and leaves the safe area genuinely clear rather than doubly cleared. The cap moves to a shared constant, because the splash screen was solving the same problem with its own copy of the number.
Populating mock data appeared to work and then emptied itself. Two emits were unguarded. `getCoins` checked the dev flag BEFORE its await and emitted after it, so a slow fetch - one RPC timing out and CoinGecko rate limiting made it 28 seconds - landed on top of the mocks whenever it finally returned. And `loadInitial` reset the list with no guard at all, which one accidental pull-to-refresh was enough to trigger. Worse, the flag stayed set afterwards, so the other guard then blocked the refetch and the panel just sat empty. Both guards lead with the `kDebugMode && kShowDevTools` const pair, so release builds fold them away and the real data path is byte-identical.
…s 171-185 The walk record is the load-bearing file: it separates what Jakub approved outright from what he decided with reasoning from what was accepted only by omission, because treating the last group as approval is how a design walk quietly invents decisions nobody made. Sketches 171 to 185 with their READMEs, phases 24 and 25, and the quick tasks behind each change in this branch. Two plans are written and NOT executed: the Menu page and the bottom-nav follow-ups. The Menu one is superseded in part - it is built around a full-screen route, and the menu is staying a bottom sheet, decided after that plan was written. It is kept for the findings it carries and its frontmatter says which parts no longer apply.
…ific row CI's quality job runs on Linux, where `/web` does not exist - `nav_destinations.dart:67` declares it `visible: !Platform.isLinux`. The test typed out `Web` as a literal, so it passed on a Mac and failed on the runner for a reason that was about the runner rather than the code. The labels now come from `moreDestinations` itself. A platform guard would have worked too, and its sibling in `mobile_nav_destinations_test.dart` uses one, but that spreads a single platform rule across two files. Deriving keeps the rule where it is declared, and the assertion follows any future conditional destination with no edit. Settings keeps its own explicit assertion on top of the derived loop. It is the destination whose loss would be worst and the one the hamburger exists to keep reachable, so it should not depend on the derivation also being correct.
…dow-wide flag Jakub on device: the Transactions section on the HOME page renders smaller than designed since the merge, and his call is to keep our sizes there. Root cause recorded rather than fixed, because the obvious fix is wrong. Develop's density pass is gated on `!useDesktopLayout(context)`, which reads the WINDOW, so on a phone it is true for the dashboard panel as well as for the page it was written for. Deleting it would fix the panel and undo real work on the page, including 44pt filter-bar touch targets. Neither `compact` nor `wide` can separate the two surfaces: the panel is ~376px and the narrow page ~390px. The recommendation is to pass density from the call site, which already knows.
Jakub, 2026-08-07: everything that goes into the repo has to be English, always. The team is not Polish-only - Brian owns Android and other people read this code - and the Polish was almost always the quote explaining WHY a decision was made, which is exactly the part a reader most needs. Provenance survives, only the language changes. A Polish quotation becomes an English rendering that still says who decided it and when, and it is NOT put in quotation marks, because those were not his words in English. Left alone on purpose: generated wallet names, network names and filenames that happen to be Polish, because they are identifiers and measured data rather than prose. Sketches from July are also untouched at his request; they are not part of this branch and pulling them in would bloat the diff with unrelated files. One correction to how this was done. The first sweep worked from a keyword list with no diacritics, so it missed eight files - including three under `lib` and `test` whose quotes were spelled with full Polish characters, and one sketch whose README was translated while its HTML was not, leaving the pair half and half. The scope is now checked with two independent patterns, diacritics and an ASCII vocabulary, over every file this branch touches.
braianxde
marked this pull request as ready for review
August 7, 2026 19:15
henriqueaklein
approved these changes
Aug 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What you hit on a phone today
The dashboard was four panels that each scrolled on their own, so the page
itself could not be scrolled and you saw four small windows instead of a
screen. Every section is now capped and the page scrolls.
The header spent 224px of 342 on one control, because the wallet pill absorbed
whatever the brand left over. It is a 44px icon beside a 44px menu button now,
a fixed 100px cluster, so nothing in the bar competes for width any more.
The bottom bar said
More, which is not a place. It now reads Home, Assets,Swap, Activity, News, and the menu moved to the header.
Assets had no page -
View allon a five-row preview led nowhere useful. Ithas a screen with search and sort.
A transaction row printed its action inside a 44.5px chip, too narrow for six
of the eight words it could hold, so it clipped the one word it existed to
show. The action leads the subtitle now.
Mock holdings emptied themselves a few seconds after you added them.
Verification
Every gate below was run on this branch, not assumed.
dart format lib testflutter analyzeflutter testcheck_brace_style.shcheck_raw_colors.shcheck_onboarding_seed_safety.shcheck_no_new_key_logging.sh --scan-treecheck_agent_rules_sync.shcheck_agent_rules_sync.shfails, and it is not this branch.AGENTS.mdand.github/copilot-instructions.mdare byte-identical toorigin/develophere(
git diff --quiet origin/develop --on both returns clean), so the driftshipped with the gate itself in #223. Fixing it means editing the agent rules,
which has nothing to do with this branch, so it is reported rather than folded
in.
developwas merged into this branch today. Two conflicts, both in thetransaction row, and both resolved by combining the two designs rather than
picking one: develop's phone-width shrink is preserved inside the rebuilt
subtitle. A third break had no conflict at all - develop added a third
_bodycall site while this branch added two required parameters to it, ondifferent lines - and only the analyzer caught it.
Seven filter-bar assertions changed from 40/183 to 52/243. That is not drift:
develop gave the phone page's filter bar its own row and raised its chips from
32 to the 44pt touch minimum. The old numbers defended title-row headroom that
this surface no longer has to share, and the comment now says the pin protects
the touch target, so a return to 183 reads as the accessibility regression it
would be.
Deliberately not here
AccountAvatardraws acurrency icon, and with the wallet name removed nothing else identifies the
account; the 16px network badge resolves to the same
eth.pngfor ETH onEthereum. The semantic label still names wallet and chain, so this is a
sighted-user gap rather than a total one. The fix - a two-character monogram
in the same circle - lives in
account_drawer.dart, outside this change.Filed as a todo.
slot's stack measures 56.85 against 60.00. Pre-existing and pinned by an
assertion; no label ever truncates horizontally. Not fixed inside a
navigation change. Filed.
real amounts run 86.5 to 136px against 113. Taking width from it was measured
as strictly worse, so it was left alone. Filed.
Minte…, a measured 7.7px short. Removingthe job hash did not touch it, because mint's context is a qualifier and mint
never printed a hash.
such a string twice; this header prints no name at all, so the defect no
longer surfaces there. It is not fixed -
import_security_screen.dartstillstores unvalidated free text. Filed.
built, and the plan is committed with a
superseded-in-partheader: it waswritten for a full-screen route, and the menu is staying a bottom sheet
because the wallet control beside it opens one, and two controls that look
alike should not behave differently.
Bad state: Cannot emit new states after calling closeappears in logs.Pre-existing and unrelated to anything here.
Reviewing on a device
--dart-define=GW_DEV_TOOLS=truefor mock data. Dark mode, phone width. Thetwo things worth a second look are the transaction subtitle - lead, context
and status must read as ONE line at ONE size, since that line is where the two
branches met - and the day labels on
/transactions, where two spacing rulescollided and the structural one was given precedence.