Skip to content

fix(mobile): enlarge icon-only controls to a reliable tap target - #6338

Open
iscekic wants to merge 1 commit into
mainfrom
kwf/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c
Open

iscekic wants to merge 1 commit into
mainfrom
kwf/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c

Conversation

@iscekic

@iscekic iscekic commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

Changelog for users

  • The Filter sessions, Rename organization, and Invite member icon controls now expose a tappable area at least 28dp on a side.
  • The active-filter count badge on Filter sessions still appears when filters are applied.
  • Pressing each control still opens the filter sheet, the rename sheet, or the invite screen as before.

Changelog for maintainers

  • New shared IconButton renders icon-only controls in a 32×32pt box with 8pt hitSlop, giving a 48pt effective target over the 28dp accessibility minimum and the 44pt DESIGN.md minimum.
  • SessionFilterButton, the organization hub rename pencil, and the members Invite member control now render through IconButton, with the icon centered in a 20pt inner box.
  • Previously these controls sized their accessibility node to the bare icon (20pt, 16pt, 22pt), which the accessibility check flagged as too small to tap.
  • Review apps/mobile/src/components/ui/icon-button.tsx first: confirm caller className merges after the default box and that any caller hitSlop override stays adequate.
  • Tests pin the box and tap-target minimums through a shared helper, and mounted tests cover each migrated control.
  • No schema, configuration, or translation changes.

E2E proof

[e2] Profile -> Organization: tap the pencil 'Rename organization' beside the organization name -> the rename sheet opens and saving a new name updates the row. — android (emulator-5604). One scripted scene from the personal Profile switched to the org ([seed:w4c-org-pair] e2e-org-owner-...), opened Manage organization, tapped the pencil, typed into 'Enter organization name' and tapped Save; e2-scene.log line 1 is 'SCENE e2 OK' and its post-save digest shows the hub header row 'android.view.View e2e-org-renamed tappable [111,167][1044,232]' where the seeded name was before (the DB row cd41b3f7-... became 'e2e-org-renamed', then I restored the 107-char seeded name in e2-restore.log so other shards are unaffected). Screenshot e2.png captured for the…

[e2] Profile -> Organization: tap the pencil 'Rename organization' beside the organization name -> the rename sheet opens and saving a new name updates the row. — prior/e2.png

Re-run the explorer's control-size scan on Agents, Organization (both entries) and Organization Members: no control under 28dp on a side is reported (previously Filter sessions 52x52px, Rename… — e5-org-members.png

[e5] Re-run the explorer's control-size scan on Agents, Organization (both entries) and Organization Members: no control under 28dp on a side is reported (previously Filter sessions 52x52px, Rename… — android (emulator-5604, density 2.625 -> 28dp = 73.5px). Scan of the four screens' a11y hierarchies (e5-agents.xml, e5-org-index.xml, e5-org-deeplink.xml, e5-org-members.xml) reports 'Filter sessions <-- scanned control 28dp-OK', 'Rename organization <-- scanned control 28dp-OK' (hub via profile entry and via the organization/ deep link) and 'Invite member <-- scanned control 28dp-OK', all measured 84x84px = 32.0x32.0dp, up from 52/42/57px; no icon control under 28dp. Screenshots e5-agents.png, e5-org-index.png, e5-org-deeplink.png, e5-org-members.png captured for the visual reviewer (not…

[e5] Re-run the explorer's control-size scan on Agents, Organization (both entries) and Organization Members: no control under 28dp on a side is reported (previously Filter sessions 52x52px, Rename… — prior/e5-org-index.png

[e5] Re-run the explorer's control-size scan on Agents, Organization (both entries) and Organization Members: no control under 28dp on a side is reported (previously Filter sessions 52x52px, Rename…

[e5] Re-run the explorer's control-size scan on Agents, Organization (both entries) and Organization Members: no control under 28dp on a side is reported (previously Filter sessions 52x52px, Rename… — prior/e5-org-deeplink.png

E2E proof — log excerpts

[e1] Open the organization deep-link entry (/(app)/(tabs)/(3_profile)/organizati -> pass :: Android emulator-5554: signed in as the org owner and switched context in Profile > account selector, opened the deep-link route and one script call reported 'SCENE e1 OK' with the rename sheet digest (Rename organization / Enter organization name / Cancel / Save) in e1-script.log; the control node content-desc="Rename organization" bounds="[914,372][998,456]" is 84x84px (32dp, above the 28dp minimum, up from the explorer's 42x42px) in e1-owner3-hierarchy.xml and e1-hub.log, the org-manage entry renders the same control at the same bounds in e1b-manage-hub.log, and the members Invite member control is 84x84px in e1-members.log; no UX defects observed.
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c/e2e-mobile-app/e1-script.log
SCENE e1 OK
android.widget.FrameLayout android:id/content tappable [0,0][1080,2400]
android.view.ViewGroup Rename organization tappable [55,270][1025,711]
android.widget.TextView Rename organization tappable [100,315][978,371]
android.widget.EditText Enter organization name tappable [100,408][978,513]
android.widget.Button Cancel tappable [625,550][806,665]
android.widget.TextView Cancel tappable [664,584][766,630]
android.widget.Button Save [833,550][979,665]
android.widget.TextView Save tappable [869,584][941,630]
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c/e2e-mobile-app/e1-hub.log
android.widget.TextView Requests tappable [581,1069][998,1106]
android.widget.TextView 0 tappable [82,1189][499,1254]
android.widget.TextView Input Tokens tappable [82,1263][499,1300]
android.widget.TextView 0 tappable [581,1189][998,1254]
android.widget.TextView Output Tokens tappable [581,1263][998,1300]
android.widget.Button Members tappable [83,1383][997,1518]
android.widget.TextView Members tappable [189,1427][933,1473]
android.widget.Button Credit activity tappable [83,1518][997,1654]
android.widget.TextView Credit activity tappable [189,1562][933,1608]
android.widget.Button Invoices tappable [83,1653][997,1788]
android.widget.TextView Invoices tappable [189,1697][933,1743]
android.widget.Button Kilo Pass. Not subscribed tappable [83,1789][997,1933]
android.widget.TextView Kilo Pass tappable [189,1817][933,1863]
android.widget.TextView Not subscribed tappable [189,1867][933,1904]
android.widget.Button Low balance alert, Off tappable [83,1933][997,2075]
android.widget.TextView Low balance alert tappable [189,1961][933,2007]
android.widget.TextView Off tappable [189,2011][933,2048]
android.view.View Home, tab, 1 of 3 tappable [0,2195][360,2337]
android.widget.TextView HOME tappable [13,2281][347,2320]
android.view.View Agents, tab, 2 of 3 tappable [360,2195][720,2337]
android.widget.TextView AGENTS tappable [373,2281][707,2320]
android.view.View Profile, tab, 3 of 3 tappable [720,2195][1080,2337]
android.widget.TextView PROFILE tappable [733,2281][1067,2320]
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c/e2e-mobile-app/e1b-manage-hub.log
android.widget.TextView 0 tappable [581,995][998,1060]
android.widget.TextView Requests tappable [581,1069][998,1106]
android.widget.TextView 0 tappable [82,1189][499,1254]
android.widget.TextView Input Tokens tappable [82,1263][499,1300]
android.widget.TextView 0 tappable [581,1189][998,1254]
android.widget.TextView Output Tokens tappable [581,1263][998,1300]
android.widget.Button Members tappable [83,1383][997,1518]
android.widget.TextView Members tappable [189,1427][933,1473]
android.widget.Button Credit activity tappable [83,1518][997,1654]
android.widget.TextView Credit activity tappable [189,1562][933,1608]
android.widget.Button Invoices tappable [83,1653][997,1788]
android.widget.TextView Invoices tappable [189,1697][933,1743]
android.widget.Button Kilo Pass. Not subscribed tappable [83,1789][997,1933]
android.widget.TextView Kilo Pass tappable [189,1817][933,1863]
android.widget.TextView Not subscribed tappable [189,1867][933,1904]
android.widget.Button Low balance alert, Off tappable [83,1933][997,2075]
android.widget.TextView Low balance alert tappable [189,1961][933,2007]
android.widget.TextView Off tappable [189,2011][933,2048]
android.view.View Home, tab, 1 of 3 tappable [0,2195][360,2337]
android.widget.TextView HOME tappable [13,2281][347,2320]
android.view.View Agents, tab, 2 of 3 tappable [360,2195][720,2337]
android.widget.TextView AGENTS tappable [373,2281][707,2320]
android.view.View Profile, tab, 3 of 3 tappable [720,2195][1080,2337]
android.widget.TextView PROFILE tappable [733,2281][1067,2320]
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c/e2e-mobile-app/e1-members.log
SCENE e1m OK
android.widget.LinearLayout com.kilocode.kiloapp:id/action_bar_root tappable [0,0][1080,2400]
android.widget.FrameLayout android:id/content tappable [0,0][1080,2400]
android.widget.Button Go back tappable [0,149][101,250]
android.view.View Members tappable [111,167][933,232]
android.widget.Button Invite member tappable [960,158][1044,242]
android.widget.TextView MEMBERS tappable [55,356][1025,393]
android.widget.TextView E2E Org Owner tappable [83,440][850,486]
android.widget.TextView e2e-org-owner-explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c@example.com tappable [83,490][850,527]
android.widget.TextView Owner tappable [895,463][979,502]
android.widget.Button Manage e2e-mobile-explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c-android tappable [55,556][1025,698]
android.widget.TextView e2e-mobile-explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c-android tappable [83,584][825,630]
android.widget.TextView e2e-mobile-explorer-a-control-is-too-small-to-tap-reliably-6790f7d4-3a6c-android@example.com tappable [83,634][825,671]
android.widget.TextView Member tappable [870,607][979,646]
android.view.View Home, tab, 1 of 3 tappable [0,2195][360,2337]
android.widget.TextView HOME tappable [13,2281][347,2320]
android.view.View Agents, tab, 2 of 3 tappable [360,2195][720,2337]
android.widget.TextView AGENTS tappable [373,2281][707,2320]
android.view.View Profile, tab, 3 of 3 tappable [720,2195][1080,2337]
android.widget.TextView PROFILE tappable [733,2281][1067,2320]
Owner request

Explorer finding: a control is too small to tap reliably

The user-agent explorer found this while using the app like a user.
One finding per item; the explorer never edits product code.

Flow: accessibility
Found on revision: fd04ca1

Repro:

  1. open the app on emulator-5554
  2. reach the screen the capture names (the screen the capture names)
  3. the capture shows the defect named below

Observed: controls below 28dp on a side: agents: 1 small control(s): Filter sessions (52x52px) org-manage: 1 small control(s): Rename organization (42x42px) org-members: 1 small control(s): Invite member (57x57px) profile-org: 1 small control(s): Rename organization (42x42px)
Expected: every control is at least 28dp on a side

Evidence (from the device run):

Follow-ups (not changed here)

  • not proved live: Agents tab: tap the sliders 'Filter sessions' control in the header -> the filter sheet opens; with a filter applied the control shows the count badge and tapping it re-opens the sheet. (no capture cited it)
  • not proved live: Open the organization deep-link entry (/(app)/(tabs)/(3_profile)/organization/) -> its Rename organization control opens the same sheet (the profile-org and org-manage entries share the control). (no capture cited it)
  • not proved live: Organization -> Members: tap the 'Invite member' icon in the header -> the invite-member sheet opens. (no capture cited it)

Open findings (not fixed here)

  • not proved live: agents.png is no longer on the host that took it, so no publish can carry it
  • not proved live: e1h.png is no longer on the host that took it, so no publish can carry it
  • not proved live: e1m.png is no longer on the host that took it, so no publish can carry it
  • not proved live: home-ar.png is no longer on the host that took it, so no publish can carry it
  • not proved live: home-dark.png is no longer on the host that took it, so no publish can carry it
  • not proved live: home.png is no longer on the host that took it, so no publish can carry it

e5-agents

Explorer finding: a control is too small to tap reliably

The user-agent explorer found this while using the app like a user.
One finding per item; the explorer never edits product code.

Flow: accessibility
Found on revision: fd04ca1

Repro:
1. open the app on emulator-5554
2. reach the screen the capture names (the screen the capture names)
3. the capture shows the defect named below

Observed: controls below 28dp on a side: agents: 1 small control(s): Filter sessions (52x52px) org-manage: 1 small control(s): Rename organization (42x42px) org-members: 1 small control(s): Invite member (57x57px) profile-org: 1 small control(s): Rename organization (42x42px)
Expected: every control is at least 28dp on a side

Evidence (from the device run):
- ~/.local/share/kwf/findings/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4/agents.png
- ~/.local/share/kwf/findings/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4/home-ar.png
- ~/.local/share/kwf/findings/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4/home-dark.png
- ~/.local/share/kwf/findings/explorer-a-control-is-too-small-to-tap-reliably-6790f7d4/home.png
@kilo-code-bot

kilo-code-bot Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Reviewed the new shared IconButton and its migration of the filter, rename, and invite controls plus the accompanying tests; no security, correctness, or regression issues found in the changed lines.

Files Reviewed (10 files)
  • apps/mobile/src/components/ui/icon-button.tsx
  • apps/mobile/src/test/touch-target.test-helpers.ts
  • apps/mobile/src/components/agents/session-filter-button.tsx
  • apps/mobile/src/components/organization/hub-screen.tsx
  • apps/mobile/src/components/organization/members-screen.tsx
  • apps/mobile/src/components/ui/icon-button.mounted.test.tsx
  • apps/mobile/src/components/agents/session-filter-button.mounted.test.tsx
  • apps/mobile/src/components/organization/hub-screen.mounted.test.tsx
  • apps/mobile/src/components/organization/members-screen.mounted.test.tsx
  • apps/mobile/src/components/agents/session-list-screen.mounted.test.tsx

Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

@iscekic

iscekic commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator Author

This description names a scenario the proof did not capture:

  • not proved live: Agents tab: tap the sliders 'Filter sessions' control in the header -> the filter sheet opens; with a filter applied the control shows the count badge and tapping it re-opens the sheet. (no capture cited it)

A repeated proof run rebuilds the same evidence, so no proof run is dispatched for a named gap. Merging with this gap open is your decision.

@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 19, 2026
@iscekic iscekic self-assigned this Sep 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

human-ready The PR is ready for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant