Work / Aakalan / Wiki / Surfaces
balances
Surfacecanonicalverified 2026-09-23
SURFACE.MOBILE.BALANCESSummary
Every person you split with, ranked, under one hero figure. The first screen after entry.
Raw wireframe
- .context/designs/mobile/balances/balances.html
Why it is drawn this way
This absorbed the Friends tab. The rule the screen already stated about a Groups tab — "a tab showing the same balance over the same list is the same screen twice" — applied just as well to Friends: same hero, same balances, same settle button, cut by person instead of by group. A cut is a segmented control, not a tab.
People is the default cut. Every verb in this half is per-person — settle, remind, confirm — and "what do I owe Sana" is the question you get asked out loud, which the Groups cut cannot answer without arithmetic.
ONE list, not two. "Owes you" and "You owe" were two headed sections over rows that already say which is which, in the one place this product reserves a colour for. Splitting them re-stated what the amount was already saying AND broke the sort, because the largest number on the screen could be stranded halfway down the second section.
All-square rows are on the list, not behind an accordion. The accordion bought eight rows of height and cost the two things this list is for: seeing who you split with, and tapping + to add the next expense. Zero is not a reason to hide someone — the person you are square with today is the one you split lunch with tomorrow.
There is no pending-settlement banner. A claim someone made is a fact about THAT PERSON, so it is an "Unconfirmed" flag on their row and the buttons live on their ledger, one tap away. The banner reserved the top of the screen for a card that is absent most days and printed the same amount twice — once in itself and once in the row directly beneath it. See person-claim.
The hero card carries the direction, not just its eyebrow. See reserved-money-direction. It is compact by design: it used to be a 32px figure over two sub-cards over a full-width Settle button, around 200px to say one number, which pushed the people that number is ABOUT below the fold.
The Settle button went with those sub-cards. It opened a person picker listing the same people already on screen — a tap to choose from a list, in order to reach a list. Every row carries its own, and that one arrives with the person already chosen.
Not-on-Aakalan rows get an invite, not a settle button. The ledger is correct for its owner and nothing reaches them, so a control that cannot land is worse than none.
The offline state is drawn here because the SyncBanner is app-wide chrome and this is where it is most often read. It sits at the BOTTOM: pinned under the status bar it landed exactly where every pushed screen puts its back arrow, so for as long as a sync problem was showing the way off ten screens was underneath it. See local-first-ledger.
There is no home flow in this set, and this is why. The first screen after
entry is the Balances tab, and the product names it Balances everywhere — tab
bar, header, (tabs)/index's own title. Naming the folder home would be the
one place in the estate where the reserved word disagreed with the word on the
screen.
Related
Sources
- src/app/(tabs)/index.tsx
- src/components/ui/balance-hero.tsx
- src/components/ui/sync-banner.tsx
Every project of mine is written down like this.
Read the résumé