Skip to content

fix(mobile): give agents filter and clear-search controls 44pt tap targets - #6406

Closed
iscekic wants to merge 1 commit into
mainfrom
kwf/explorer-a-control-is-too-small-to-tap-reliably-8b3897c4-033b
Closed

iscekic wants to merge 1 commit into
mainfrom
kwf/explorer-a-control-is-too-small-to-tap-reliably-8b3897c4-033b

Conversation

@iscekic

@iscekic iscekic commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

Changelog for users

  • The Agents session-filter control now carries a full 44pt tap target, so it is easier to hit.
  • The clear-search control inside the Agents search field now carries a full 44pt tap target.
  • The filter's active-count badge stays attached to the glyph instead of the enlarged touch box.

Changelog for maintainers

  • Both controls now set a 44pt minimum box on the pressable itself, because hitSlop widens touches but not the accessibility node bounds a tap-target audit measures (WCAG 2.5.8 AA).
  • The filter button wraps its glyph and count badge in an inner view so the badge anchors to the glyph, not the 44pt box.
  • New mounted tests assert each control declares at least 28dp per side, matching the audit threshold, and that the clear control is absent while the field is empty.
  • The rewritten search-header test file drops the landscape sensor-inset assertions; that layout logic is unchanged but is no longer covered.
  • Review first: apps/mobile/src/components/agents/session-filter-button.tsx and apps/mobile/src/components/agents/session-list-search-header.tsx.

E2E proof

[e2] On the Agents tab, type 'zzzz-no-such-session' into the search field so the agents-search-empty state shows: the audit reports both the filter control and the in-field clear-search X at least 28dp on… — android emulator-5554: search-empty shows 'android.widget.TextView No sessions match tappable [360,1083][720,1148]'; filter 'Filter sessions tappable [907,165][1022,281]'=115x116px and in-field X 'android.widget.Button Clear search tappable [868,340][984,455]'=116x115px, both 43.8-44.2dp >= 28dp (e2-search-empty-light.log, density.log); tapping the in-field X restored the list, 'android.widget.TextView Verifier echo test tappable [93,627][958,673]' with no clear control (e2-after-clear-light.digest.txt). Declared trigger deviates: a brand-new empty account renders the no-sessions centered…

On the Agents tab, type 'zzzz-no-such-session' into the search field so the agents-search-empty state shows: the audit reports both the filter control and the in-field clear-search X at least 28dp on… — e2-search-empty-light.png

[e2] On the Agents tab, type 'zzzz-no-such-session' into the search field so the agents-search-empty state shows: the audit reports both the filter control and the in-field clear-search X at least 28dp on…

[e2] On the Agents tab, type 'zzzz-no-such-session' into the search field so the agents-search-empty state shows: the audit reports both the filter control and the in-field clear-search X at least 28dp on… — e2e-mobile-app/e2-search-empty-light.png

E2E proof — log excerpts

[e1] On emulator-5554 in light mode, open the Agents tab and run the tap-target  -> pass :: android emulator-5554, density 420 (2.625px/dp, 28dp=73.5px): filter node 'android.widget.Button Filter sessions tappable [907,165][1022,281]' = 115x116px = 43.8x44.2dp >= 28dp (e1-agents.digest.txt, density.log); tapping it opened the sheet, digest shows 'android.widget.TextView PLATFORM' and 'android.widget.Button Apply tappable [821,704][979,820]' (e1-filter-sheet.log).
[e2] On the Agents tab, type 'zzzz-no-such-session' so agents-search-empty shows -> pass :: android emulator-5554: search-empty shows 'android.widget.TextView No sessions match tappable [360,1083][720,1148]'; filter 'Filter sessions tappable [907,165][1022,281]'=115x116px and in-field X 'android.widget.Button Clear search tappable [868,340][984,455]'=116x115px, both 43.8-44.2dp >= 28dp (e2-search-empty-light.log, density.log); tapping the in-field X restored the list, 'android.widget.TextView Verifier echo test tappable [93,627][958,673]' with no clear control (e2-after-clear-light.digest.txt). Declared trigger deviates: a brand-new empty account renders the no-sessions centered state with no search field, so the state was reached on the signed-in account (one session seeded via se
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-a-control-is-too-small-to-tap-reliably-8b3897c4-033b/e2e-mobile-app/e1-agents.digest.txt
hierarchy: /tmp/kilo-hierarchy.3wdKeO
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.TextView 1 LIVE tappable [58,149][698,186]
android.view.View Agents tappable [58,190][698,296]
android.widget.Button See all tappable [724,203][870,242]
android.widget.TextView SEE ALL tappable [724,203][870,242]
android.widget.Button Filter sessions tappable [907,165][1022,281]
android.widget.EditText Search sessions tappable [163,340][984,449]
android.widget.Button Verifier echo test, Idle, PANON-DEKING, and Just now tappable [0,549][1080,709]
android.widget.TextView PANON-DEKING tappable [93,583][778,620]
android.widget.TextView JUST NOW tappable [822,583][957,620]
android.widget.TextView Verifier echo test tappable [93,627][958,673]
android.widget.Button New session tappable [881,2006][1028,2153]
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-8b3897c4-033b/e2e-mobile-app/density.log
hw.lcd.density=420
hw.lcd.height=2400
hw.lcd.width=1080
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-a-control-is-too-small-to-tap-reliably-8b3897c4-033b/e2e-mobile-app/e1-filter-sheet.log
SCENE e1 MISS screen 'Preferences' at capture
android.widget.FrameLayout android:id/content tappable [0,0][1080,2400]
android.view.ViewGroup Filter sessions tappable [55,216][1025,866]
android.view.View Filter sessions tappable [100,261][978,317]
android.widget.TextView PLATFORM tappable [101,355][979,392]
android.widget.CheckBox Cloud tappable [101,401][979,493]
android.widget.TextView Cloud tappable [202,423][952,469]
android.widget.TextView PROJECT tappable [101,530][979,567]
android.widget.CheckBox iscekic/panon-deking tappable [101,576][979,668]
android.widget.TextView iscekic/panon-deking tappable [202,598][952,644]
android.widget.Button Cancel tappable [613,704][794,820]
android.widget.TextView Cancel tappable [652,738][754,784]
android.widget.Button Apply tappable [821,704][979,820]
android.widget.TextView Apply tappable [857,738][941,784]
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-a-control-is-too-small-to-tap-reliably-8b3897c4-033b/e2e-mobile-app/e2-search-empty-light.log
SCENE e2 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.TextView 1 LIVE tappable [58,149][698,186]
android.view.View Agents tappable [58,190][698,296]
android.widget.Button See all tappable [724,203][870,242]
android.widget.TextView SEE ALL tappable [724,203][870,242]
android.widget.Button Filter sessions tappable [907,165][1022,281]
android.widget.EditText Search sessions tappable [163,343][850,452]
android.widget.Button Clear search tappable [868,340][984,455]
android.widget.ScrollView centered-state tappable [0,555][1080,2400]
android.view.ViewGroup centered-state-content tappable [0,918][1080,1356]
android.widget.TextView No sessions match tappable [360,1083][720,1148]
android.widget.TextView Try a different search term. tappable [339,1157][741,1203]
android.widget.Button Clear search tappable [408,1240][672,1356]
android.widget.TextView Clear search tappable [447,1274][633,1320]
android.widget.Button New session tappable [881,2006][1028,2153]
android.view.View Home, tab, 1 of 3 tappable [0,2195][360,2337]
android.view.View Agents, tab, 2 of 3 tappable [360,2195][720,2337]
android.view.View Profile, tab, 3 of 3 tappable [720,2195][1080,2337]
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-a-control-is-too-small-to-tap-reliably-8b3897c4-033b/e2e-mobile-app/e2-after-clear-light.digest.txt
hierarchy: /tmp/kilo-hierarchy.TD5221
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.TextView 1 LIVE tappable [58,149][698,186]
android.view.View Agents tappable [58,190][698,296]
android.widget.Button See all tappable [724,203][870,242]
android.widget.TextView SEE ALL tappable [724,203][870,242]
android.widget.Button Filter sessions tappable [907,165][1022,281]
android.widget.EditText Search sessions tappable [163,340][984,449]
android.widget.Button Verifier echo test, Idle, kilo/astral-flux-zwo, PANON-DEKING, and 9 minutes ago tappable [0,549][1080,755]
android.widget.TextView PANON-DEKING tappable [93,583][694,620]
android.widget.TextView 9 MINUTES AGO tappable [738,583][957,620]
android.widget.TextView Verifier echo test tappable [93,627][958,673]
android.widget.TextView kilo/astral-flux-zwo tappable [93,683][958,720]
android.widget.Button New session tappable [881,2006][1028,2153]
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: 5327758

Repro:

  1. set this state first: the device in light mode
  2. open the app on emulator-5554
  3. reach the screen named agents, agents-search-empty
  4. the capture shows the defect named below

Observed: controls below 28dp on a side: agents: 1 small control(s): تصفية الجلسات (53x53px) agents-search-empty: 2 small control(s): تصفية الجلسات (53x53px); مسح البحث (42x42px)
Expected: every control is at least 28dp on a side

Evidence (from the device run):

Open findings (not fixed here)

  • not proved live: agents-search-empty.png is no longer on the host that took it, so no publish can carry it
  • not proved live: agents.png is no longer on the host that took it, so no publish can carry it

@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

The incremental commit adds the two tests the earlier review asked for: the landscape sensor-inset margin case and the single-line input min-h-only height invariant, and both assertions match the component's current behavior.

Files Reviewed (1 file)
  • apps/mobile/src/components/agents/session-list-search-header.mounted.test.tsx
Previous Review Summary (commit 0252fea)

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

Previous review (commit 0252fea)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1

Source changes are correct: both controls now carry a real 44pt box instead of relying on hitSlop, and the badge re-anchoring to an inner glyph view preserves its offset. The only finding is dropped test coverage in the rewritten search-header test.

Issue Details (click to expand)

SUGGESTION

File Line Issue
apps/mobile/src/components/agents/session-list-search-header.mounted.test.tsx 71 Rewrite drops the landscape sensor-inset and min-h input-height assertions; safe-area mock is pinned to zero insets so fieldMargins is only covered in portrait.
Files Reviewed (4 files)
  • apps/mobile/src/components/agents/session-filter-button.tsx - 0 issues
  • apps/mobile/src/components/agents/session-filter-button.mounted.test.tsx - 0 issues
  • apps/mobile/src/components/agents/session-list-search-header.tsx - 0 issues
  • apps/mobile/src/components/agents/session-list-search-header.mounted.test.tsx - 1 issue

Fix these issues in Kilo Cloud


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

Review guidance: REVIEW.md from base branch main

@iscekic
iscekic marked this pull request as draft September 19, 2026 23:28
@iscekic
iscekic force-pushed the kwf/explorer-a-control-is-too-small-to-tap-reliably-8b3897c4-033b branch from 0252fea to 85f772a Compare September 19, 2026 23:53
@iscekic
iscekic marked this pull request as ready for review September 20, 2026 00:05
@iscekic

iscekic commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator Author

This description names a scenario the proof did not capture:

  • not proved live: agents-search-empty.png is no longer on the host that took it, so no publish can carry 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 requested a review from eshurakov September 20, 2026 00:28
@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 20, 2026
@iscekic
iscekic requested a review from pandemicsyn September 20, 2026 00:28
@iscekic iscekic self-assigned this Sep 20, 2026
@iscekic

iscekic commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator Author

Closing as a duplicate of #6395.

This PR and ten others came from the same explorer finding, a-control-is-too-small-to-tap-reliably. Nine of the eleven edit apps/mobile/src/components/agents/session-filter-button.tsx, so they could never all merge — the first to land would conflict the rest.

#6395 is kept because it is the broadest of the group (14 files of the 34 the group touches).

Any screen still below the tap-target bar after #6395 merges will be found again by the same scan, and will now arrive as one finding: the intake refuses a finding whose slug already has an open PR or a live section (kwf 07c842fd).

@iscekic iscekic closed this Sep 20, 2026
@iscekic iscekic reopened this Sep 20, 2026
@iscekic

iscekic commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator Author

Reopened — I closed this in error.

I closed it as a duplicate of #6395 on the grounds that eleven PRs shared one explorer finding. That was right about the finding and wrong about this PR: it is not a subset of #6395. It changes files #6395 does not touch, so closing it discarded real work rather than removing a copy.

Checked properly: of the ten I closed, only #6365 and #6363 are true subsets of #6395. The other eight, including this one, each fix a screen or a helper the keeper leaves alone.

What remains true: these PRs overlap on apps/mobile/src/components/agents/session-filter-button.tsx, so they will conflict with each other and cannot all merge as they stand. That is a sequencing problem to resolve, not a reason to throw the work away.

Apologies for the churn.

@iscekic

iscekic commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator Author

Closing so this defect has one PR instead of nine.

All nine came from the same explorer finding, a-control-is-too-small-to-tap-reliably, on different screens. Nine of them edit apps/mobile/src/components/agents/session-filter-button.tsx, so the first to merge conflicts the rest — they were never all mergeable.

#6395 is kept as the broadest (14 files).

I reopened this PR earlier today after closing it, because it is not a subset of #6395 and I did not want to pretend otherwise. The work it carries is not being dropped: the six source files across this group that #6395 does not touch are now one queued item, tap targets on the screens the first pass did not cover, which names each component and the PR it came from —

  • components/agents/session-list-header-actions.tsx
  • components/login/idle-auth.tsx
  • components/organization/hub-screen.tsx
  • components/organization/members-screen.tsx
  • components/ui/icon-button.tsx
  • lib/a11y/tap-target.ts (the shared helper)

One change through the shared helper is a better answer than nine screen-by-screen edits that conflict.

Cause, now fixed: each finding was dispatched the moment it was found. The explorer pools findings for an hour and dispatches one item per defect (kwf d25ae7de), and the intake refuses a slug that already has open work (kwf 07c842fd).

@iscekic iscekic closed this Sep 20, 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