Skip to content

fix(mobile): 44dp touch targets, accessibility, and tokenized model-picker#4385

Merged
iscekic merged 7 commits into
mainfrom
mobile-ui-audit
Jul 3, 2026
Merged

fix(mobile): 44dp touch targets, accessibility, and tokenized model-picker#4385
iscekic merged 7 commits into
mainfrom
mobile-ui-audit

Conversation

@iscekic

@iscekic iscekic commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes the remediation phases of .plans/mobile-readability-touch-target-audit.md. The audit report itself is in .plans/mobile-ui-audit-findings.md (not committed, per repo policy on plans).

Touch targets and accessibility

  • agents/chat-composer.tsx: send/stop now have hitSlop reaching 44dp, plus accessibilityRole, accessibilityLabel, and accessibilityState.
  • profile-avatar-button.tsx: full 44dp box (h-11 w-11) with accessibilityRole and pressed feedback.
  • screen-header.tsx: title dropdown gets 44dp hitSlop + role/label; the back button now has accessibilityRole="button".
  • agents/session-list-screen.tsx (plus/filter): 44dp-reaching hitSlop, accessibilityRole, pressed feedback. The facing slops are capped at 8 so the two expanded targets don't overlap inside the 16px gap (overlapping sibling hit rects let the later sibling steal taps).

Readability

  • ui/session-row.tsx, ui/configure-row.tsx: replace text-[10.5px] / text-[11.5px] / text-[14.5px] arbitrary sizes with the nearest sanctioned text-xs / text-sm utilities.
  • app/(app)/(tabs)/_layout.tsx: raise tab-label font size from 10px to 11px (with small letter-spacing).

Tokenization (no more hardcoded brand-blue)

  • kiloclaw/model-picker.tsx: selected state moves from border-blue-500 bg-blue-500/5 + #3b82f6 to border-primary bg-neutral-100 dark:bg-neutral-800 + colors.primary (the established selected-card pattern from exec-policy.tsx; an opaque bg-accent-soft fill was tried first but is #E8F27A in both themes, which made dark-mode card text and the primary-colored checkmark illegible). Decorative Balanced / Frontier icon tints now use the existing agent-sky / agent-yuki tile-bg tokens. The 'or select from 500+ models' link is enlarged to a 44dp target with accessibilityRole='link' and a label.
  • kiloclaw/settings/model-list.tsx: selected Check color → colors.primary.
  • agents/child-session-section.tsx: running-tool icons / text / border move from #3b82f6 / text-blue-500 to the agent-sky token set (theme-aware light + dark).

Out of scope: chat gutters (already consistent at px-4 on both message-bubble.tsx files), status-badge palettes (green / red / blue is a deliberate semantic set), the model-picker performanceDotColor dots (same deliberate-decorative category), and the eyebrow / 10-11px metadata typography (intentional per the design contract).

A size='touch' Button variant and an a11y-enforcing IconButton wrapper were originally added in ui/button.tsx but dropped in review: nothing consumed them, and knip ignores src/components/ui/** so they would have shipped as permanently unchecked dead code. They can return in the same PR as their first call site.

Verification

Manual device verification is required but was not done by the agent (no simulator / device access in this worktree). Items to spot-check on iOS and Android, light + dark:

  • ChatComposer (agent chat): tap reliability and VoiceOver / TalkBack announcement of 'Send message' / 'Stop generating'.
  • SessionHeader (ScreenHeader with onTitlePress): title now announces 'Open menu for <title>'. Back button announces as a button.
  • Profile avatar, Agents list plus / filter: tap reliability near the screen edge, and that a tap between the plus and filter icons hits the intended control.
  • KiloClaw model picker: selected card contrast in light + dark (neutral fill + primary border/check); the 'select from 500+ models' link target.
  • SessionRow / ConfigureRow long-title truncation (already had numberOfLines={1}, now at text-sm / text-xs).
  • Tab bar at default and 130% Dynamic Type: 'KiloClaw' label still fits the 64dp content width.

Automated checks: pnpm format, pnpm typecheck (mobile + full repo), pnpm lint, pnpm test (360/360), pnpm check:unused all clean.

Visual Changes

Visual changes are limited to:

  • Tab labels slightly larger (10 → 11px) at the bottom of every screen.
  • KiloClaw model picker selected state changes from a blue ring to a brand yellow-green (primary) border on a neutral fill (bg-neutral-100 / dark:bg-neutral-800).
  • SessionRow and ConfigureRow row titles / subtitles are 1-2px larger.
  • All hitSlop changes are invisible; they expand the tap area without changing visual size.

Screenshots were not captured by the agent; visual confirmation is part of the manual checklist above.

Reviewer Notes

Seven small commits; the last one applies review findings (dark-mode selected-card contrast, overlapping hitSlop rects, dropping the unused IconButton/touch surface, ThemeColors type reuse, double 'selected' screen-reader announcement).

Risk areas

  • getStatusBorderColor in child-session-section.tsx now takes the full ThemeColors object instead of just destructiveColor. Tested only by typecheck and existing tests.
  • The asymmetric hitSlop insets on the session-list header buttons trade ~3dp of horizontal target for non-overlapping hit rects; vertical targets stay at 44dp.

iscekic added 6 commits July 3, 2026 16:17
- Add size='touch' (44dp) to the Button primitive for entry points
  that need a comfortable tap target.
- Add an IconButton typed wrapper that requires accessibilityLabel at
  the type level so icon-only buttons always have a screen-reader name.
- profile-avatar-button: wrap the 22dp icon in a 44dp container with
  pressed feedback and hitSlop.
- screen-header title dropdown: bump hitSlop so the effective target
  reaches 44dp; add accessibilityRole and accessibilityLabel derived
  from the title.
- session-list-screen plus/filter: bump hitSlop to 44dp, add
  accessibilityRole and pressed feedback.
Add hitSlop so the 32dp send/stop Pressables reach a 44dp effective
target. Add accessibilityRole, accessibilityLabel ('Send message' /
'Stop generating'), and accessibilityState to match the back-button
pattern in ScreenHeader.
Replace arbitrary text-[10.5px] / text-[11.5px] / text-[14.5px] in
SessionRow and ConfigureRow with the nearest sanctioned size utilities
(text-xs / text-sm) so row titles and subtitles read at the floor of
comfortable legibility.
- KiloClaw model-picker: replace hardcoded blue selected state
  (border-blue-500, bg-blue-500/5, #3b82f6) with the brand primary
  token (border-primary, bg-accent-soft, colors.primary) so the
  selected indicator matches the rest of the product. Tokenize the
  decorative 'Balanced' / 'Frontier' icon tints to the existing
  agent-sky / agent-yuki tile-bg tokens. Enlarge the 'or select from
  500+ models' link to a 44dp target with accessibilityRole='link'
  and a label.
- KiloClaw settings model-list: selected check color → colors.primary.
- agents child-session-section: replace '#3b82f6' / text-blue-500 with
  agent-sky tokens so the running-tool indicator matches the brand
  palette and uses theme-aware dark variants.
Raise the tab-bar label fontSize from 10px to 11px (with a small
letter-spacing) so functional navigation identifiers read at the
floor of legibility. Keeps JetBrains Mono to match the eyebrow
pattern used elsewhere in the app.
@iscekic iscekic self-assigned this Jul 3, 2026
@kilo-code-bot

kilo-code-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Reviewed all 11 changed files (touch-target/accessibility additions, tokenized colors, and text-size normalization) and found no security, runtime, or logic issues in the changed lines.

Files Reviewed (11 files)
  • apps/mobile/src/app/(app)/(tabs)/_layout.tsx
  • apps/mobile/src/app/(app)/kiloclaw/[instance-id]/settings/model-list.tsx
  • apps/mobile/src/components/agents/chat-composer.tsx
  • apps/mobile/src/components/agents/child-session-section.tsx
  • apps/mobile/src/components/agents/session-list-screen.tsx
  • apps/mobile/src/components/kiloclaw/model-picker.tsx
  • apps/mobile/src/components/profile-avatar-button.tsx
  • apps/mobile/src/components/screen-header.tsx
  • apps/mobile/src/components/ui/button.tsx
  • apps/mobile/src/components/ui/configure-row.tsx
  • apps/mobile/src/components/ui/session-row.tsx

Reviewed by claude-sonnet-5-20260630 · Input: 42 · Output: 17.5K · Cached: 1.2M

Review guidance: REVIEW.md from base branch main

… drop unused IconButton

- model-picker: selected card used opaque bg-accent-soft (#E8F27A in both
  themes), leaving near-white text and a primary-colored checkmark invisible
  in dark mode; switch to the established border-primary bg-neutral-100
  dark:bg-neutral-800 selected pattern (exec-policy.tsx)
- model-picker: drop ', selected' from accessibilityLabel — the
  accessibilityState already announces selection (was announced twice)
- session-list header: Plus (hitSlop 11) and Filter (hitSlop 12) expanded
  rects overlapped by 7px inside the 16px gap, so the later sibling stole
  taps; cap the facing slops at 8
- profile avatar: remove redundant hitSlop on an already 44dp box (also
  overlapped the filter button's slop)
- screen-header: add accessibilityRole to the back button
- button.tsx: drop the unused IconButton wrapper and touch size variant
  (no consumers; knip ignores ui/**, so it would ship as unchecked dead code)
- child-session-section: use the exported ThemeColors type
@iscekic iscekic requested a review from jeanduplessis July 3, 2026 15:59
@iscekic iscekic enabled auto-merge (squash) July 3, 2026 16:03
@iscekic iscekic merged commit 21f5668 into main Jul 3, 2026
18 of 19 checks passed
@iscekic iscekic deleted the mobile-ui-audit branch July 3, 2026 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants