Skip to content

fix(mobile): show the Kilo Pass Manage button label - #8077

Merged
iscekic merged 3 commits into
mainfrom
drain/kilo-pass-manage-label
Oct 22, 2026
Merged

iscekic merged 3 commits into
mainfrom
drain/kilo-pass-manage-label

Conversation

@iscekic

@iscekic iscekic commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Change

The Manage button under "This Kilo Pass is managed on web" on the Kilo Pass screen rendered as a blank rectangle on device: its label was passed to the shared Button as a bare string child. Button renders its children inside a Pressable (a View), and a View draws no text, so the control collapsed to its padding (~22x25 dp) while the accessibility tree still named the button.

Two changes:

  • apps/mobile/src/components/ui/button.tsx: the shared Button now wraps string and number children in its themed label Text (the classes the TextClassContext provider already publishes), so every caller's scalar label renders. Element children pass through untouched. This closes the bug class for all current and future call sites; the other seven Button call sites that pass non-Text children pass icon elements, which already rendered.
  • apps/mobile/src/components/kilo-pass/kilo-pass-subscription-screen.tsx: the Manage CTA carries an explicit <Text> label and min-h-[48px], so the lone centered call-to-action meets the 48 dp Android touch target without hitSlop (nothing sits beside it). Default size stays min-h-[44px] elsewhere.

Verification

  • Targeted suites: button.mounted.test.tsx (25) and kilo-pass-subscription-screen.test.ts (5) pass; both carry new regression assertions — the primitive wraps scalar children in the themed label Text, and the screen renders the Manage button with a labeled child and the 48 dp class.
  • pnpm typecheck (mobile) clean; oxlint clean on the four changed files.
  • Android emulator (API 36, 420 dpi), local dev stack + Metro, dark mode, Hindi locale, signed in with a fake local account holding an active Stripe-provider Kilo Pass row:
    • Before this branch the same screen rendered the blank rectangle (finding evidence).
    • After: the button shows the visible label प्रबंधित करें, and the accessibility tree reports the clickable node at 218x126 px = 83.0 x 48.0 dp (the 126 px height is exactly 48 dp at 420 dpi).
    • Screenshot attached in the comments below.

Proxy answers

The owner's proxy gave these answers in the owner's place.

  1. Question: Touch target: How should the Manage button reach the 48 dp target? The default Button size renders min-h-[44px]; the work item asks for at least 48 dp.
    Answer: min-h-[48px] on this button (Recommended)
    Confidence: 0.75 · Precedent: Engineering conventions / UX: best-in-class standard with clearance and right-sized targets (session 00eb2a1d3e4b, "design and UX MUST BE BEST-IN-CLASS"). The work item explicitly asks for 48 dp, and the button has no adjacency cost.
  2. Question: Guard: Beyond fixing this button, what guard should the PR carry against the bare-string-child class of bug?
    Answer: Harden the shared Button so it wraps string and number children in its themed label Text instead of rejecting or ignoring them. That fixes the class in all 8 files. Remove the now-redundant manual wrapping only where it is trivial. Add a regression test on the Button primitive, plus the kilo-pass screen assertion. Run the targeted tests for the touched files and let CI run the rest.
    Confidence: 0.60 · Precedent: Autonomy: fix the root cause and the class of the issue on every affected surface (session 00eb2a1d3e4b, "if anything repeats the same mistake over over again, fix the class").
  3. Question: Scope: Two glanceable-ios live-activity files have the same bare-string Button child pattern. Include them?
    Answer: Fix them in this PR
    Confidence: 0.55 · Precedent: Autonomy: fix the class on every affected surface (session 75f8833fe8c1, "fix this for all shared services model pickers on all surfaces"). Ask for an iOS lane to verify; an agent may request one (session 2f71af3a787e).

Note on the third answer: the two glanceable-ios files were surveyed and do NOT use the shared Button — they import Button from @expo/ui/swift-ui, and their children are SwiftUI Text elements returned by a pill() helper, which render. No change was needed there; this is recorded rather than implemented because the premise of the answer (the same bare-string pattern) did not hold on inspection.

The Manage button on the Kilo Pass screen passed its label as a bare
string child. Button renders into a Pressable (a View), and a View
draws no text, so the control collapsed to its padding and showed no
label while the accessibility tree still named it. The shared Button
now wraps string and number children in its themed label Text, and the
Manage CTA carries an explicit Text label plus a 48dp minimum height
for the Android touch target.
@iscekic iscekic added drain Work item from the findings drain explorer:android Finding surfaced by the Android explorer labels Oct 19, 2026
@iscekic

iscekic commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

bot: End-to-end proof on the Android emulator (API 36, 420 dpi), local dev stack + Metro, dark mode, Hindi locale, fake local account with an active web-managed Kilo Pass: the Manage call-to-action renders its visible label, and the accessibility tree reports the clickable node at 218x126 px = 83.0 x 48.0 dp, meeting the 48 dp touch target.

Kilo Pass screen in dark mode with visible Manage label at 48 dp

@kilo-code-bot

kilo-code-bot Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The new array-child normalization in the shared Button is consistent with the scalar path, keeps element entries unwrapped, and its added regression test matches the implementation; no defects found in the incremental change.

Files Reviewed (2 files)
  • apps/mobile/src/components/ui/button.tsx
  • apps/mobile/src/components/ui/button.mounted.test.tsx
Previous Review Summary (commit df625c6)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit df625c6)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The shared Button scalar-label normalization and the Kilo Pass CTA sizing are correct, consistent with the existing Bubble scalar-child pattern, and covered by new regression tests; no defects found in the changed code.

Files Reviewed (4 files)
  • apps/mobile/src/components/ui/button.tsx
  • apps/mobile/src/components/ui/button.mounted.test.tsx
  • apps/mobile/src/components/kilo-pass/kilo-pass-subscription-screen.tsx
  • apps/mobile/src/components/kilo-pass/kilo-pass-subscription-screen.test.ts

Notes: cn() uses tailwind-merge, so the call-site min-h-[48px] correctly overrides the default min-h-[44px]; wrapped scalar labels inherit TextClassContext and hasRtlScript/containsJoinedScript safely accept non-string children. No memory-leak or lifecycle concerns introduced.


Reviewed by deepseek-v4.1-flash-1017 · Input: 93.1K · Output: 10.7K · Cached: 619.6K

Review guidance: REVIEW.md from base branch main

Follow-up to the scalar-label normalization: children arrays get the
same per-entry treatment, and whitespace-only string entries are left
unwrapped so JSX spacing idioms between an icon and a labeled element
keep their current behaviour (they draw nothing in a View, and the
row gap does the spacing). Adds a regression test for both.
@iscekic

iscekic commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Follow-up commit a772155: the Button label normalization now also covers array children per entry, while whitespace-only string entries (the JSX {" "} spacing idiom) stay unwrapped so icon-plus-label buttons keep their current spacing behaviour. A regression test covers both. Surveyed all Button call sites: no current caller passes mixed element-plus-raw-scalar children, so nothing else changes. Full mobile suite green: 1190 files, 17875 passed / 2 skipped.

@iscekic iscekic added merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. merge:human Substantive functional risk requires human review. and removed merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. merge:human Substantive functional risk requires human review. labels Oct 19, 2026
@iscekic
iscekic added this pull request to the merge queue Oct 21, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drain Work item from the findings drain explorer:android Finding surfaced by the Android explorer merge:bot Bot-owned review; merge when ready once readiness passes and a review approves.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants