Appearance
Home — design-to-implementation gap list
Design pulled: prototype/mobile-console/Home.dc.html + console-kit.js from the Claude Design PROTOTYPE project 633dc069-6df8-4408-b625-068907c60c33, fetched 2026-08-15 via DesignSync. Not a local cache, not Home_v1/Home_v2 (both superseded by Home.dc.html).
Implementation compared: apps/mobile/src/tiers/user/features/dashboard/screens/DashboardHome/** at 5c71ade, plus apps/mobile/src/app/(user)/(tabs)/_layout.tsx and the @/ui primitives each element resolves through.
This is a BASELINE, not a work order
No code was changed to produce it. Every row is a measured difference between two files, with both values quoted. Rows marked recorded are approved divergences that already carry a drift-ledger row — they are listed so the list is complete, not because they need fixing.
Method, so this is repeatable for the next screen
- Pull the screen from the prototype project. Never the design-system project (that holds components, not screens — QRS-451), never a local copy.
- Read the design's own template AND the JS that supplies its values — half the contract is in
renderVals, not in the markup. - Resolve every implementation value to a number, following it through the
@/uiprimitive and the token.variant="caption"is not a comparable value;12px/500is. - Record differences with both sides quoted. "Close enough" is not a verdict.
What MATCHES — verified, not assumed
Listed because a gap list that only shows gaps implies everything else was checked and it usually was not.
| Element | Verified |
|---|---|
| Section order | greeting → quick actions → share strip → KPI strip → needs attention → first-run/groups. Identical to the design's template order. |
| Fixed vs scrolling chrome | Header, rule, season and offline banners sit OUTSIDE the scroll container in both (flex:none in the design, chrome prop here). |
| Scroll bottom padding | 108px both. |
| Centre navigation button | 60×60, radius 24 (--r-xl), 3px surface-raised border, brand gradient, plus glyph at 28px in accent-contrast, offset top:-20. Exact match including the 56px reserved span it overhangs. |
| Tab bar | surface-raised, 1px border-subtle top, paddingHorizontal:20, paddingTop:10, gap 4, minWidth:50, icon 24, label 11px/700, active accent-active / inactive content-tertiary. Unread badge 18px, paddingHorizontal:5, 2px surface-raised ring, danger fill. |
| Tab set + labels | Home · Chats · Store · More, in that order, with "Store" (not "Catalogue"). |
| KPI tile geometry | gap 8, paddingHorizontal:18, paddingTop:4, minHeight:64, padding:12, inner gap 5, radius 18 (--r-lg), value 19px/800 mono. |
| Quick-action tile geometry | 44×44 pill icon, grid gap 4, paddingHorizontal:14, paddingBottom:6, tile paddingVertical:8. |
| Greeting block box | paddingTop:6, paddingHorizontal:14, paddingBottom:12, gap 3; heading 22px/800. |
| Avatar radius | 36px at radius 10 = --r-sm. |
GAPS
G1 · Header has no horizontal inset — HIGH, visible
- Design: header container
padding:0 14px 10px. - Implementation:
HomeHeader's root is<View className="flex-row items-center gap-2">with no padding, andDashboardShellrenders{chrome}with no inset either. - Effect: header content sits flush to the screen edges while the rule directly beneath it is inset 14px (
marginHorizontal: PAD.text). The header and its own underline do not share an edge.
G2 · No gap between header and the rule — HIGH, and this is the owner's reported symptom
- Design: header carries
padding-bottom:10px, then the rule addsmargin-bottom:11px. - Implementation: header has no bottom padding; the rule has
marginBottom:11only. - Effect: the separator sits 0px below the header controls instead of 10px. Reported verbatim as "the padding around the separator line is too tight, and the separator is almost touching the header icons." Confirmed as a real measurement, not a perception.
G3 · Header icon buttons are 32×32, design says 44×44 — HIGH, also an a11y floor breach
- Design: the bell is
width:44px;height:44px;border-radius:50%,1px solid var(--border),background:var(--surface-raised). - Implementation:
<IconButton size={sizing.control.sm}>andsizing.control.smis 32 (packages/tokens/src/tokens.ts:250). - Effect: the two header controls are 12px smaller per side than designed, which shortens the whole header band and is most of the "proportions do not match" report. It is also below the 44px touch target the repo's own layout-invariants measurement enforces — the
run-mobileskill already records "32×32 Notifications, 32×32 Profile" as violations the e2e gate currently misses. - ⚠ The owner-avatar control next to them is correctly 44×44, so the row currently mixes 32 and 44.
G4 · Business name typography — MEDIUM
| Design | Implementation | |
|---|---|---|
| size | 14px | 14.5px |
| weight | 800 | 700 |
| tracking | -.01em | none set |
console-kit's own rule #3 is "Type comes from the scale 11 12 13 14 16 18 22 27 36. No half points." — 14.5 is off-scale by that rule.
G5 · Business tagline: wrong size AND wrong value — MEDIUM structure, HIGH content
- Size. Design
font-size:11px,--content-tertiary. Implementationvariant="caption"which resolves to 12px / weight 500 (tokens.ts:193). - Value. Design computes
bizTagline = ind.label + ' · ' + ind.area— the industry label and the area. The implementation passesdata.category, which is still the stub"Café · Bandra West". - ⚠
get_my_contextdoes not project an industry label or an area today, so closing the content half is a read change, not a component change. It cannot be fixed insideHomeHeader.
G6 · Business avatar colours — MEDIUM
- Design:
background:var(--accent), textvar(--accent-contrast),font-size:13px, weight 800,letter-spacing:-.02em. - Implementation:
Avatarfills withc['accent-soft']and draws initials inc['content-secondary']atsize * 0.36(12.96px). - Effect: the design's business chip is a solid accent block with contrast text; ours is a soft tint with secondary text — a visibly lower-contrast, lower-emphasis element in the highest position on the screen.
- The design's own note: "everything else on the screen that used to be gradient (the business avatar) is
var(--accent)" — so the solid accent is a deliberate decision, not an accident of the mock.
G7 · Header item gap — LOW
Design gap:10px; implementation gap-2 = 8px.
G8 · Quick-action label size — LOW
Design font-size:10.5px with min-height:26px; implementation fontSize: 11. (Note the design itself uses a half-point here, against its own type-scale rule — worth raising with the design project rather than silently matching or silently ignoring.)
G9 · Scan & collect tile absent — KNOWN, tracked
The design's quickActionsVM pushes four tiles: Scan & collect → Orders → Collections (all three gated on the orders capability) → Payments (gated on payments). Ours omits the first because ScanCollect is not built (QRS-645) and the design's own rule is that a tile whose tap dead-ends teaches the merchant the surface is unreliable.
G10 · The whole quick-action row is invisible on the owner's workspace — DATA, not code
All four tiles are capability-gated on orders / payments. Both resolve false for the owner's workspace in Dev, so hasQuickActions is false and the design's own behaviour is to render nothing. The component is correct; the grants are not. Same single condition also explains the two missing Quick-tools entries. Needs a feature-grant fix in Dev, not a client change.
G11 · First-run and groups are mutually exclusive here — NEEDS A DESIGN RULING
The design renders <sc-if isFirstRun> steps and then runs the groups loop as a sibling, not an else. The implementation is firstRun ? <FirstRunSteps/> : <DashboardGroups/>. Whether a first-run workspace with resolvable groups should show both is a design question — do not guess it; it is the kind of ambiguity this process exists to surface rather than resolve unilaterally.
G12 · Reminders panel is an extra section — RECORDED DIVERGENCE
Round 22's Home has no reminders panel. Kept by owner decision, QRS-663, because reminders is shipped and the design has never been asked to place it. Drift-ledger row exists.
G13 · Reminders clock is a fourth header control — RECORDED DIVERGENCE
The design's header is exactly three controls (workspace chip · bell · owner avatar). Kept by owner decision, same row as G12.
Not yet compared — stated rather than implied
To keep this list honest about its own coverage. None of these were examined element-by-element:
AttentionRailinternals (card 84% flex-basis, 96px min-height,--r-xl, tinted 30px icon, CTA pill 30px, dismiss 44px hit box).SeasonBannerandOfflineBannerinternals (design:--r-md,accent-soft/surface-muted, 12px copy, 44px dismiss).HeroCardvsShareCardStrip(design:padding:19px 20px 18px, radius--r-2xl, handle at 27px/800, body 13.5px/500 at opacity .82, CTA 38px pill, copy "Share your Setu Card to collect more reviews, bookings and payments.", CTA label "View my Setu Card").FirstRunStepsinternals.- Individual widget bodies inside
WidgetBody.tsx(stats / bar / chips / bars / spark / ring / activity / slot) against their eight design branches. - Dark theme for every element above.
- Interaction states (pressed / focus / disabled / loading) on any element.
Sequencing
Fix in the order G1 → G2 → G3, because all three change the header band's height and re-measuring after each one individually is wasted work. G5's content half and G10 are backend items and do not belong in the same change as the styling ones.