Skip to content
Ritesh FirodiyaGet in touch

Work / AskCal / Wiki / Surfaces

portion

Surfacecanonicalverified 2026-09-28

SURFACE.MOBILE.FOOD.PORTION

Summary

How much of this did you have — one editor, worn as a weight, a count or a pour.

Raw wireframe

  • .context/designs/mobile/food/portion-weight.html
  • .context/designs/mobile/food/portion-count.html
  • .context/designs/mobile/food/portion-liquid.html

Why it is drawn this way

Three files, one screen, one route. food/item.tsx renders all three. Which face it wears is a fact about the food, not a choice the user makes, so there is no face-picker anywhere.

They are generated from one template — scripts writes the four editors (these three and fat) from a single anatomy, because three hand-written faces of one screen drift, and had: different section labels, quick-picks on one face only, and the unit-weight row on one face only.

The anatomy, top to bottom:

Zone What it holds
Header item name, the meal it is in, and a bin
Label + mark "Portion", and the confidence mark for this row
Value the number, its unit, and the kcal it comes to
Derived grams only where the unit is not already grams
Stepper the one control you came here to use
Quick picks four presets, so the common answer is one tap
Footer rows what one piece weighs, and what share you ate — each opens a sheet
Macros the macros of the portion above
"Not this?" wrong amount and wrong food are one complaint to someone over a plate

A cooking-fat row never reaches this screen. Every caller branches on isFatComponent and sends it to fat instead, because "how much oil" is a judgement with named answers rather than a food to weigh or re-identify. meal.tsx always did; result.tsx did it for the row's button but not for the tap on its name, so this editor grew a fat face whose only content was a card linking to the screen the row already offered. The branch is in the callers now and the face is gone.

Grams are the quantity of record. A face may speak in pieces or millilitres, but grams is what macros scale from, and lib/measure.ts holds the invariant grams === gramsFor(measure). The derived gram line is printed so the two can never silently disagree, and it is never editable from here.

The share is descriptive, never arithmetic. "Half of it" records that the portion above was half of what arrived; it recomputes nothing. See the sheet below. The alternative — where choosing half halves the number — makes one control mean two different things depending on whether the stepper was already touched, and nothing can tell which the user meant.

The "You ate" sheet

Five options: all of it, most of it, half, a third, a quarter. It is a sheet rather than five rows left open, because a share is set occasionally and the quantity is set every time. Drawn in sheets.

It earns its place on things nobody can count — a curry, a bowl of rice, a plate shared between two. Half of two eggs is one egg, which the stepper says better.

Related

Sources

  • .context/designs/mobile/food/portion-weight.html

Every project of mine is written down like this.

Read the résumé