fix(ios): honor layout weight in stacks - #98
Conversation
GenericJam
commented
Aug 29, 2026
Validated on device. The change works — with a correctly built binary, weight distributes on both axes: a row's two One finding worth addressing before people build weighted panels on this. The weight frame sits on the wrong side of the child's backgroundRan the same probe on both platforms — two weighted panels with backgrounds, in a row and in a column. Android: each panel's background fills its half — full-width colour bars in the row, half-height blocks in the column. iOS with this PR: the panels are positioned at the same half-points, but their backgrounds hug their text inside an expanded, invisible frame. The cause is modifier ordering. Android passes the weight MobNodeView(node: child).mobColumnWeight(child.layoutWeight)
Worth noting This matters because weighted layout's common case is colored panels splitting a screen: correct on Android, wrong on iOS, and silent. Two minor notes
The tests can't see this. They're grep-based source-contract tests asserting the strings exist, so they pass whether or not the layout behaves — green CI says nothing about whether weight works. That's inherent to testing native layout from Elixir and matches the existing Unrelated gotcha found while verifying
|
4c4663a to
18872a1CompareGenericJam
commented
Aug 30, 2026
Adversarially reviewed and device-verified on a pool iPhone 17 Pro sim (harness app with :mob path-dep on this branch, verified via Mob.Test.element_frames + real UITouch injection). Approve. Verified numerically: single weighted child expands to fill (342 = 402−60 remainder); two weighted children split evenly per the updated docs (201/201 — iOS deliberately doesn't do Android's numeric ratios, and guides/components.md now says so accurately); weighted middle child pins trailing footer flush to container bottom; weighted :spacer works (the generic mob_node_from_dict parse covers every node type); the expanded frame is genuinely tappable to its far edge and the frame registry reports expanded geometry (modifier ordering weight → offset → FrameTracker is right). Host suite 1203 passed, credo --strict clean, warnings-as-errors clean. Android untouched (ios/* + docs + test only). Coexistence check for downstream consumers: a weighted child alongside a size-less expanding Spacer does NOT double-expand — the Spacer collapses to its ~8pt minLength. Safe to ship before consumers remove their workarounds. Non-blocking follow-ups worth tracking: (1) the new test pins source strings rather than behavior — an :on_device frame-assertion test would survive refactors; (2) content inside the expanded frame is hardcoded top/leading, so a weighted Button's label leading-pins on iOS where Compose centers it — cosmetic parity nuance; (3) weighted nodes with translucent backgrounds or borders get double-painted decoration (intrinsic + expanded) — invisible for opaque fills, visible artifact for translucent/bordered; (4) weight: 0/negative unvalidated (Android throws at runtime). Also found pre-existing and unrelated: MobBox ignores height unless width is also set (fixedHeight only applied inside the fixedWidth > 0 branch, MobRootView.swift ~764-776) — filing separately. Merging. |
Uh oh!
There was an error while loading. Please reload this page.
Summary
weightinto the iOS native node modelVerification
mix credo --strictmix compile --warnings-as-errors