Touch & iPad review
Audit React + Tailwind apps for finger-first interaction on iPad and touch screens. Skip generic advice (use semantic HTML, be responsive, etc.) — only flag non-obvious gaps.
Checklist: references/tailwind-touch-checklist.md
When to run
User prompt like: "review app for touch/iPad usage" or "review app for this use case" with touch/tablet context.
Review workflow
- Scan interactive UI — buttons, links, icon buttons, tabs, map controls, dropdowns / menus / Listbox, inline selectable sidebar rows, drag handles, form controls, custom click targets (
onClick on non-button elements).
- Walk the checklist — classify lists as Bucket A (Headless UI / Radix) vs Bucket B (custom
<button> rows); grep helps (hover:, data-focus:, focus &&, MenuItem, ListboxOption, onClick, cursor-, group-hover).
- Test mentally for iPad — Split View width changes, sticky hover, touch-over highlight (press-drag-release in open menus and inline lists), double-tap zoom, keyboard covering inputs, thumb reach for primary actions.
- Emit the report using the template below — every finding must have location, issue, and concrete Tailwind/React fix.
Do not list passing generic practices. Group duplicates (e.g. "12 icon buttons missing min size") into one finding with representative files.
Report template
Copy this structure into the response:
# Touch / iPad review — [app or scope]
## Summary
[2–3 sentences: overall risk, top themes]
## Findings
### Critical
| # | File / component | Issue | Suggested fix |
| --- | ---------------- | ----- | ------------------------------- |
| 1 | `path:line` | … | Tailwind classes or code change |
### Warning
| # | File / component | Issue | Suggested fix |
| --- | ---------------- | ----- | ------------- |
### Nice to have
| # | File / component | Issue | Suggested fix |
| --- | ---------------- | ----- | ------------- |
## FMC conventions verified
- [ ] All `<a>` and `<button>` (and tappable custom controls) use `cursor-pointer` on desktop
- [ ] Interactive controls use `select-none` where text selection would flash on iPad
- [ ] Hover-only affordances gated with fine-pointer media (see checklist)
- [ ] Menu/list rows: touch-over via `data-focus:` / `focus` (Headless UI) or `data-[highlighted]:` (Radix) — not `hover:` alone
- [ ] Inline sidebar pickers flagged if hover-only (Bucket B)
## Passed (non-obvious)
[Only items you explicitly checked and that are correct — keep short]
Severity
| Level |
When |
| Critical |
Broken on touch, inaccessible tap, hidden functionality, mis-tap risk on primary flows |
| Warning |
Substandard but usable; sticky hover; targets slightly small; missing feedback |
| Nice to have |
Consistency, thumb-zone polish, haptics N/A on web |
FMC defaults (always check)
Apply on every review:
| Rule |
Tailwind / code |
| Desktop pointer on links & buttons |
cursor-pointer on <a>, <button>, and tappable custom controls |
| No iOS text-selection flash on controls |
select-none on buttons, icon buttons, tabs, chips used as controls |
| Fine-pointer-only hover |
Do not use bare hover: for essential UI; use [@media(hover:hover)_and_(pointer:fine)]:hover:… (or project variant — see checklist) |
Quick grep hints
# Hover without fine-pointer guard (manual triage)
rg 'hover:' --glob '*.{tsx,jsx}'
# Small tap targets
rg '<(button|a)[^>]*(size-[0-9]|h-[0-9]|w-[0-9])' --glob '*.tsx'
# Div click traps
rg 'onClick' --glob '*.tsx' | rg -v '<button|<a '
# Missing cursor on interactives (heuristic)
rg '<(button|a) ' --glob '*.tsx' | rg -v 'cursor-pointer'
# Headless UI menus: hover without touch-over styling
rg 'MenuItem|ListboxOption|menuItemClasses' --glob '*.tsx'
rg 'hover:bg' --glob '*Menu*.tsx' --glob '*Listbox*.tsx' --glob '*Dropdown*.tsx'
# Inline sidebar rows: hover-only selection feedback
rg "hover:bg.*onClick|onClick.*hover:bg" --glob '*.tsx'
External references
1---2name: touch-ipad-review3description: Reviews React web apps for iPad and touchscreen usability with Tailwind CSS fixes. Audits touch targets, hover failures, touch-over list highlighting (Headless UI data-focus, Radix data-highlighted, inline rows), Safari/iPadOS quirks, layout fluidity, and FMC cursor conventions. Use when the user asks to review an app for touch, iPad, tablet, or touchscreen-optimized usage.4---56# Touch & iPad review78Audit React + Tailwind apps for **finger-first** interaction on iPad and touch screens. Skip generic advice (use semantic HTML, be responsive, etc.) — only flag non-obvious gaps.910**Checklist:** [references/tailwind-touch-checklist.md](references/tailwind-touch-checklist.md)1112## When to run1314User prompt like: _"review app for touch/iPad usage"_ or _"review app for this use case"_ with touch/tablet context.1516## Review workflow17181. **Scan interactive UI** — buttons, links, icon buttons, tabs, map controls, **dropdowns / menus / Listbox**, **inline selectable sidebar rows**, drag handles, form controls, custom click targets (`onClick` on non-button elements).192. **Walk the checklist** — classify lists as **Bucket A** (Headless UI / Radix) vs **Bucket B** (custom `<button>` rows); grep helps (`hover:`, `data-focus:`, `focus &&`, `MenuItem`, `ListboxOption`, `onClick`, `cursor-`, `group-hover`).203. **Test mentally for iPad** — Split View width changes, sticky hover, **touch-over highlight** (press-drag-release in open menus and inline lists), double-tap zoom, keyboard covering inputs, thumb reach for primary actions.214. **Emit the report** using the template below — every finding must have **location**, **issue**, and **concrete Tailwind/React fix**.2223Do **not** list passing generic practices. Group duplicates (e.g. "12 icon buttons missing `min size`") into one finding with representative files.2425## Report template2627Copy this structure into the response:2829```markdown30# Touch / iPad review — [app or scope]3132## Summary3334[2–3 sentences: overall risk, top themes]3536## Findings3738### Critical3940| # | File / component | Issue | Suggested fix |41| --- | ---------------- | ----- | ------------------------------- |42| 1 | `path:line` | … | Tailwind classes or code change |4344### Warning4546| # | File / component | Issue | Suggested fix |47| --- | ---------------- | ----- | ------------- |4849### Nice to have5051| # | File / component | Issue | Suggested fix |52| --- | ---------------- | ----- | ------------- |5354## FMC conventions verified5556- [ ] All `<a>` and `<button>` (and tappable custom controls) use `cursor-pointer` on desktop57- [ ] Interactive controls use `select-none` where text selection would flash on iPad58- [ ] Hover-only affordances gated with fine-pointer media (see checklist)59- [ ] Menu/list rows: touch-over via `data-focus:` / `focus` (Headless UI) or `data-[highlighted]:` (Radix) — not `hover:` alone60- [ ] Inline sidebar pickers flagged if hover-only (Bucket B)6162## Passed (non-obvious)6364[Only items you explicitly checked and that are correct — keep short]65```6667**Severity**6869| Level | When |70| ------------ | -------------------------------------------------------------------------------------- |71| Critical | Broken on touch, inaccessible tap, hidden functionality, mis-tap risk on primary flows |72| Warning | Substandard but usable; sticky hover; targets slightly small; missing feedback |73| Nice to have | Consistency, thumb-zone polish, haptics N/A on web |7475## FMC defaults (always check)7677Apply on **every** review:7879| Rule | Tailwind / code |80| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |81| Desktop pointer on links & buttons | `cursor-pointer` on `<a>`, `<button>`, and tappable custom controls |82| No iOS text-selection flash on controls | `select-none` on buttons, icon buttons, tabs, chips used as controls |83| Fine-pointer-only hover | Do not use bare `hover:` for essential UI; use `[@media(hover:hover)_and_(pointer:fine)]:hover:…` (or project variant — see checklist) |8485## Quick grep hints8687```bash88# Hover without fine-pointer guard (manual triage)89rg 'hover:' --glob '*.{tsx,jsx}'9091# Small tap targets92rg '<(button|a)[^>]*(size-[0-9]|h-[0-9]|w-[0-9])' --glob '*.tsx'9394# Div click traps95rg 'onClick' --glob '*.tsx' | rg -v '<button|<a '9697# Missing cursor on interactives (heuristic)98rg '<(button|a) ' --glob '*.tsx' | rg -v 'cursor-pointer'99100# Headless UI menus: hover without touch-over styling101rg 'MenuItem|ListboxOption|menuItemClasses' --glob '*.tsx'102rg 'hover:bg' --glob '*Menu*.tsx' --glob '*Listbox*.tsx' --glob '*Dropdown*.tsx'103104# Inline sidebar rows: hover-only selection feedback105rg "hover:bg.*onClick|onClick.*hover:bg" --glob '*.tsx'106```107108## External references109110- [Apple HIG — Accessibility (44×44 pt targets)](https://developer.apple.com/design/human-interface-guidelines/accessibility)111- [Apple HIG — Designing for iPadOS](https://developer.apple.com/design/human-interface-guidelines/designing-for-ipados)112- [WCAG 2.2 — Target Size (2.5.8)](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html)113- [Touch target practices (Capi Product)](https://www.capiproduct.com/post/10-best-practices-for-designing-effective-touch-targets-in-mobile-ui)114- [Design for Touch (Design+Code / iOS handbook)](https://designcode.io/ios-design-handbook-design-for-touch)115- [Mobile app design best practices (RapidNative)](https://www.rapidnative.com/blogs/mobile-app-design-best-practices)