Skip to content

fix(mobile): mobile-first audit — touch-size form controls + reorder issue fields#45

Merged
bryankennedy merged 3 commits into
mainfrom
mobile-first-audit
Jun 30, 2026
Merged

fix(mobile): mobile-first audit — touch-size form controls + reorder issue fields#45
bryankennedy merged 3 commits into
mainfrom
mobile-first-audit

Conversation

@exe-dev-github-integration

Copy link
Copy Markdown
Contributor

Mobile-first audit

A rendered phone-viewport audit (360 / 390 / 430 / 768 + 1440 desktop regression, with touch + DPR emulation) of the highest-traffic views — Board, Issue page, New-issue dialog, Agenda, Structure — following the bottom-tab-bar nav (PROG-79). Every finding is grounded in a screenshot + measured probe, not a code read.

Verdict: after PROG-79 the app is usable one-handed with no horizontal-scroll or off-screen-CTA defects — but every form control triggered iOS zoom-on-focus and sat under the 44px touch floor, and the issue page buried its primary action fields under a long activity log. Those are fixed here.

Blocking — none

PROG-79 removed the top-nav overflow; the board's horizontal scroll is contained to its own overflow-x-auto strip (intentional, D30); the page itself doesn't scroll sideways; the new-issue modal fits at 360px with Cancel/Create reachable; viewport meta is correct (viewport-fit=cover, zoom enabled).

High — fixed

  • [H1] iOS zoom-on-focus on every form control. Board/Agenda/Search filters, the new-issue dialog, and the issue sidebar all rendered text-xs = 14.4px < 16px, so focusing any select/date field makes iOS Safari zoom in and stay zoomed. Fixed with a global @media (max-width:639px) rule forcing form controls to 16px (unlayered so it beats Tailwind's text-xs utility). Probe verified: smallInputs=0 at 360/390/430.
  • [H2] Issue page buried its action fields on mobile. flex-col md:flex-row stacked the field strip (Status/Priority/Estimate/Due/Container/Arc/Tags) after the description and the full activity timeline — so on a heavily-edited issue you scrolled past dozens of rows to change status. Rebuilt as a CSS grid: mobile flows description → fields → timeline; desktop is byte-identical (content left, fields right). Verified at 390 (fields now directly under the description) and 1440 (unchanged).
  • [H3] Form-control touch targets < 44px. Filter/dialog/date controls were ~36px tall. Same media block adds min-height:44px (never shrinks taller fields like the comment box). Verified: zero sub-44 form controls at 390 across all audited views.

Medium / Low — documented, deferred (to keep this PR tight)

  • [M1] Small issue-page text-links ("Move… (M)" ~19px, "Change…", "Edit…", "Copy as prompt", breadcrumbs ~26px).
  • [M2] Structure + Product / + Arc / + Repo buttons ~26px (low-frequency curation).
  • [M3] Header buttons / avatar slightly under 44px.
  • [L1] Keyboard hints in labels ("(C)", "(M)", "⌘K for commands") are meaningless on touch.
  • [L2] New-issue is a centered modal vs a bottom sheet (fits at 360px, so polish).

Hard calls (mobile-first)

  • One global form-control rule, not per-component — covers surfaces with bespoke <select> markup (Agenda, the dialog) that a shared-component fix would miss, and prevents drift. Costs the dense desktop nothing (scoped to ≤639px).
  • Issue page uses an explicit grid over duplicating the timeline or flex order hacks — mobile reorders, desktop stays identical.
  • Deferred M/L target-sizing so this stays a verifiable form-controls + field-order change rather than a sprawling touch-up.

Verification

tsc -b clean; bun run test → 84 pass. Re-rendered the full phone matrix after fixing: smallInputs=0 and zero sub-44 form controls at 360/390/430; issue fields above the timeline on mobile; desktop issue + board unchanged.

A rendered phone-viewport audit found every dense (text-xs) form control —
the board/agenda/search filters, the new-issue dialog, the issue sidebar —
rendering at 14.4px, under the 16px floor below which iOS Safari zooms-on-focus
and stays zoomed; many were also ~36px tall, under the 44px touch target floor.

Add one rule in @media (max-width: 639px): input/select/textarea get
font-size:16px and min-height:44px (checkboxes/radios excepted; min-height never
shrinks a taller field like the comment box). One global rule covers surfaces
with bespoke <select> markup that a per-component fix would miss, and prevents
drift. It's unlayered on purpose — Tailwind's text-xs utility sits in a cascade
layer, and unlayered rules win over any layer regardless of specificity, so the
element selector takes effect without !important. Scoped to phones so the dense
desktop sizing is untouched.
…meline

On a phone the issue layout (flex-col md:flex-row) stacked the field aside —
Status/Priority/Estimate/Due/Container/Arc/Tags/Work-on-this — after both the
description and the full comments+activity timeline, so on a heavily-edited
issue you scrolled past dozens of activity rows just to change status.

Rebuild the layout as a CSS grid: the single-column mobile flow follows source
order (description → field strip → timeline), while desktop pins content to the
left column across both rows and the fields to the right column via explicit
col-start/row-start/row-span — leaving the desktop view unchanged. Avoids
duplicating the timeline behind hidden/md:hidden (double mount) and flex order
hacks that can't express the desktop two-row right column cleanly.
Add the audit's two opinionated mobile-first calls to DECISIONS — the global
phone form-control sizing (16px / 44px, why global + unlayered + phone-scoped)
and the issue-page field-order grid (why a grid over duplication / flex order).
@bryankennedy bryankennedy merged commit ab7b3dc into main Jun 30, 2026
2 checks passed
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.

1 participant