Skip to content

The holdings page reads as panels, and every page title heads its content - #230

Merged
braianxde merged 4 commits into
developfrom
redesign/assets-boxed-panels-260808
Aug 10, 2026
Merged

The holdings page reads as panels, and every page title heads its content#230
braianxde merged 4 commits into
developfrom
redesign/assets-boxed-panels-260808

Conversation

@SirYakoob

Copy link
Copy Markdown

Stacked on #227. Base is redesign/row-rhythm-260808, so the diff here is only today's Assets
work. It retargets to develop automatically when #227 merges.

What a user hits

The holdings page finally looks like the rest of the app. Assets was the only unboxed list we
ship: Home wraps every panel in DashboardScrollContainer, Activity wraps its transaction list in
the same container on a phone, Markets draws a card per coin and News one per article - and Assets
hung its rows on raw surface-base. It now uses two panels: the portfolio total, then the search,
the count and sort line, and the rows.

The "‹ HOME" back link is gone. It was written when the only way onto the page was the
dashboard's View all. Assets has been the bottom bar's second tab since the S7 bar landed, and a
tab has no back - Home is one tap away on the same screen. Activity, the tab beside it, never had
one either.

The page frame is the shared one. Assets was the single page-header screen hardcoding a 64px top
gap and a 12px gutter while every sibling calls pageTitleGap / pageGutter (24 and 6 on a phone).
Measured on device, its title sat 40px lower and 6px further in than the Transactions title.

Every page title moved in, not just this one. Titles sat flush with the frame gutter while
everything the page says - kickers, coin names, row icons, transaction rows - sat 15px further in, so
the title read as having escaped to the left of its own page. The inset now lives in GWPageHeader,
so Assets, Activity, Markets, News, Banxa, the coin page and the job form move together. It is
derived from the panel container (its hairline + its padding + the space4 wall GWSectionTitle and
kGWRowWall share), which puts a title at 21 on a phone - the exact X the dashboard's own section
titles land on.

Also: the portfolio total was a private widget inside coins_screen.dart and is now shared, so the
dashboard panel and the page cannot disagree about a number the user reads as one fact.

Verification

All run, not assumed:

Gate Result
flutter analyze No issues found
flutter test 1207 passed, 3 skipped - unchanged from before this branch
dart format lib test clean (3 files reformatted, included here)
check_brace_style / check_raw_colors / check_onboarding_seed_safety / check_no_new_key_logging --scan-tree PASS
check_agent_rules_sync FAIL, and it is not from this branch - see below

The dashboard's Assets panel is proven byte-identical after the shared-widget extraction:
assets_header_scheme_a_test reports the same boxH=32.0, drop=0.125 and header=94.0 it did
before.

Walked on an iPhone 14 (390pt) via hot reload while building.

Deliberately not here

  • check_agent_rules_sync fails. AGENTS.md and CLAUDE.md are out of sync, neither file is
    touched by this branch, and the same mismatch is on develop - it arrived with One rules file for every agent on the team #223. Reported
    rather than fixed silently, because a rules-file edit is not something to smuggle into a UI PR.
  • Transactions keeps its filter track outside its panel. Sketch 188 recommends moving it inside
    so the two neighbouring tabs draw a list the same way; that is its own change and its own review.
  • The row content width drops from 362 to 348 at 390pt (gutter + card border + card padding + row
    wall). The amount column was already measured clipping at that width, so a known defect gets 14px
    worse. It is the same 14px Activity already pays, and matching the app beat keeping one page wider
    than every other. The clipping itself has a todo of its own.
  • On plain GWCard pages the title lands near its text, not on it - a card's padding is not a
    panel's. One inset shared by every title, so the tabs agree with each other, beat four insets that
    each agree with one page and no other.
  • Light mode. Dark-first, as agreed; the tokens used here are the shared ones, so the light pass
    has nothing page-specific to undo.

Reading the diff

The three code commits stand alone and are worth reading in order: the shared total band, then the
page, then the header component. The fourth is planning docs only - sketches 187 and 188, where 188
corrects a factual claim 187 made, annotated in place rather than quietly rewritten.

The portfolio total was a private widget inside coins_screen.dart, which was
fine while the dashboard panel was the only surface printing it. The /assets
page is about to print the same number, and two copies of a number the user
reads as one fact drift: the type, the colour, or the optical centring of the
24h percentage would sooner or later disagree between the two screens.

Promoted verbatim - same tokens, same space4 inset, same
CrossAxisAlignment.center that fixed the percentage hanging low. The
dashboard's rendered tree is unchanged, and the header test proves it: the
same boxH 32.0, drop 0.125 and header 94.0 it measured before.

The test's finder moved with it. It matched the private type by name, and the
test file declares its OWN AssetsTotalBand as a measurement probe, so the
shipping widget is imported with a prefix rather than either being renamed - a
probe called something else drifts out of step with what it claims to mirror.
Assets was the only unboxed list in the app. Home wraps every panel in
DashboardScrollContainer, Activity wraps its transaction list in the same
container on a phone, Markets draws a card per coin and News one per article -
and Assets hung its rows on raw surface-base. The page now uses two panels:
the portfolio total, then the search, the count and sort line, and the rows.

Two things a user hits, fixed on the way:

The back link is gone. It read "< HOME" and was written when the only way onto
this page was the dashboard's View all. Assets has been the bottom bar's
second tab since the S7 bar landed, and a tab has no back - Home is one tap
away on the same screen. The sibling tab Activity carries no back link either,
so the two now agree.

The page frame is the shared one. This screen hardcoded a 64px top gap and a
12px gutter while every other page-header screen calls pageTitleGap and
pageGutter, which are 24 and 6 on a phone. Measured on device, the Assets
title sat 40px lower and 6px further in than the Transactions title.

Cost, accepted deliberately: a boxed row has 348px of content at 390pt where a
flat one has 362. The amount column was already measured clipping at that
width, so this makes a known defect 14px worse. It is the same 14px Activity
already pays, and matching the app beat keeping one page wider than the rest.
Every page title sat flush with the frame gutter while everything the page
actually says - section kickers, coin names, row icons, transaction rows - sat
15px further in. The title read as having escaped to the left of its own page.
Walked on device on Assets, then asked for across the tabs.

The inset is derived from the app's panel container rather than picked: the
1px hairline it draws, the padding it charges (which switches on the same
breakpoint the container does), and the space4 wall GWSectionTitle and
kGWRowWall already share inside it. At 390pt that puts a title at 21 from the
screen edge, which is the exact X the dashboard's own section titles land on -
so "Assets" on the page now lines up with "Assets" on Home. space8 was
rejected as a tidier single token: it lands at 22 and misses the content
column by a pixel, and an alignment off by one is worse than one that is
deliberately different.

It lives in the component, so Assets, Activity, Markets, News, Banxa, the coin
page and the job form all move together instead of drifting apart.

Two costs, named rather than found later. The centred form (Swap, Feedback's
header style) is exempt - it sits inside a centred card column, not above a
content column. And on plain GWCard pages the title lands near its text rather
than on it, because a card's padding is not a panel's; one inset shared by
every title, so the tabs agree with each other, beats four that each agree
with one page and no other.

Three tests encoded the old flush-with-the-container rule. They are repointed,
not deleted, and each now reads the inset from the component inside the pumped
tree, so the component and its tests can no longer drift apart.
… them

Sketch 187 asked whether /assets needs a breadcrumb and whether it should be
boxed like the Home panels. Sketch 188 asked the same of Transactions - and
answered a factual question that reversed 187's own recommendation, so 187 is
annotated in place rather than quietly rewritten: its finding that no full
page uses DashboardScrollContainer is false, and Assets was the only unboxed
list in the app.

Also records the quick task that implemented the winner, including the title
inset chosen on device and the two costs it carries.
@braianxde
braianxde marked this pull request as ready for review August 10, 2026 11:03
Base automatically changed from redesign/row-rhythm-260808 to develop August 10, 2026 12:24
// follow-up, held back only so it does not confound the review of
// the title treatment this change is actually for.
if (total > 0) ...[
const SizedBox(width: GeniusWalletConsts.space4),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the spacing property

@braianxde
braianxde merged commit ead8910 into develop Aug 10, 2026
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.

3 participants