diff --git a/.planning/phases/31-mobile-polish/31-RESEARCH.md b/.planning/phases/31-mobile-polish/31-RESEARCH.md new file mode 100644 index 0000000..92b187a --- /dev/null +++ b/.planning/phases/31-mobile-polish/31-RESEARCH.md @@ -0,0 +1,143 @@ +# Phase 31: Mobile Polish — Research + +**Researched:** 2026-04-12 +**Status:** Complete +**Focus:** Icon-based action buttons on mobile detail pages + +## Standard Stack + +- **Component library:** None (plain Tailwind CSS v4) +- **Icon library:** lucide-react via `LucideIcon` component (`src/client/lib/iconData.tsx`) +- **Styling:** Tailwind CSS v4 with `@import "tailwindcss"` (no custom tokens, no config file) +- **Responsive pattern:** `md:` breakpoint (768px) — matches BottomTabBar (`md:hidden`) and TopNav (`hidden md:flex`) + +## Action Button Inventory + +### 1. Item Detail (`src/client/routes/items/$itemId.tsx`) + +**Location:** Top bar, right side (lines ~190-213) +**Current pattern:** Text-only buttons in a `flex items-center gap-2` container +**Edit mode:** Visible when `!isEditing` + +| Button | Text | Current Classes | Icon Candidate | +|--------|------|----------------|----------------| +| Duplicate | "Duplicate" | `px-3 py-1.5 text-sm text-gray-500 hover:text-gray-700 hover:bg-gray-50 rounded-lg` | `copy` (16px) | +| Delete/Remove | "Delete" or "Remove from Collection" | `px-3 py-1.5 text-sm text-red-400 hover:text-red-600 hover:bg-red-50 rounded-lg` | `trash-2` (16px) | +| Edit | "Edit" | `px-4 py-1.5 text-sm font-medium text-white bg-gray-700 hover:bg-gray-800 rounded-lg` | `pencil` (16px) | + +**Edit mode buttons (Cancel/Save):** These should remain text buttons even on mobile — users need clear text feedback during edit operations. + +### 2. Candidate Detail (`src/client/routes/threads/$threadId/candidates/$candidateId.tsx`) + +**Location 1:** Header area — Edit button inline with heading (line ~282-289) +**Current pattern:** Small text+icon button (`LucideIcon name="pencil" size={14}` + "Edit" text) + +**Location 2:** Bottom actions area (lines ~530-548) +**Current pattern:** Text+icon buttons in `flex gap-3 pt-4 border-t border-gray-100` + +| Button | Text | Current Pattern | Icon Candidate | +|--------|------|----------------|----------------| +| Edit (header) | "Edit" | `px-3 py-1.5 text-sm` + pencil icon 14px | Already has icon — hide text on mobile | +| Pick as Winner | "Pick as winner" | `px-4 py-2` + trophy icon 14px | `trophy` (16px) | +| Delete | "Delete" | `px-4 py-2` + trash-2 icon 14px | Already has icon — hide text on mobile | + +### 3. Setup Detail (`src/client/routes/setups/$setupId.tsx`) + +**Location:** Toolbar area below header (lines ~155-210) +**Current pattern:** Mixed text+icon and text-only buttons in `flex items-center gap-3` + +| Button | Text | Current Pattern | Icon Candidate | +|--------|------|----------------|----------------| +| Add Items | "Add Items" | `px-4 py-2` + inline SVG plus icon | `plus` (16px) via LucideIcon | +| Public toggle | "Public"/"Private" | `px-3 py-2` + inline SVG globe | `globe` (16px) via LucideIcon | +| Delete Setup | "Delete Setup" | `px-4 py-2 text-red-600 bg-red-50` | `trash-2` (16px) | + +**Note:** Setup page uses inline SVGs instead of LucideIcon — migration to LucideIcon is a natural cleanup. + +### 4. Global Item Detail (`src/client/routes/global-items/$globalItemId.tsx`) + +**Location:** Action buttons below image (lines ~167-193) +**Current pattern:** Text-only buttons in `flex gap-3 mb-6` + +| Button | Text | Current Pattern | Icon Candidate | +|--------|------|----------------|----------------| +| Add to Collection | "Add to Collection" | `px-5 py-2.5 bg-gray-700 text-white` | `plus` (16px) | +| Add to Thread | "Add to Thread" | `px-5 py-2.5 bg-white border` | `message-square-plus` (16px) | + +## Architecture Patterns + +### Recommended Implementation Pattern + +Use paired hidden/visible elements with responsive Tailwind classes: + +```tsx +{/* Desktop: text + optional icon */} + + +{/* Mobile: icon-only with touch target */} + +``` + +### Alternative: Single Element with Responsive Text Hiding + +```tsx + +``` + +**Recommendation:** Use the paired-element approach for cleaner code and independent styling control. The single-element approach has too many responsive overrides. + +**Alternative considered and rejected:** A shared `IconActionButton` component. The action buttons across pages have different styling (primary, secondary, destructive), different sizes, and different hover states. A shared component would need too many props and wouldn't simplify the code meaningfully for just 4 pages. + +### LucideIcon Migration for Setup Page + +The setup detail page uses inline SVGs for the plus icon and globe icon. These should be migrated to `LucideIcon` for consistency: +- Plus SVG → `` +- Globe SVG → `` + +### Touch Target Sizing + +- Minimum 44x44px per WCAG 2.5.5 (AAA) / Apple HIG +- Achieved with `min-w-[44px] min-h-[44px]` on mobile icon buttons +- Desktop buttons keep current sizing (no min-width needed) + +### Edit Mode Buttons + +Cancel and Save buttons during edit mode should **remain text buttons** on both mobile and desktop: +- These are contextual actions that need clear text labels +- Edit mode is a temporary state — users need to see "Cancel" and "Save" text clearly +- No risk of button crowding since they replace the action buttons + +## Dependencies + +None. This phase is self-contained — only modifies existing button rendering in 4 route files. + +## Risks + +1. **Low risk:** Button group layout may need adjustment on very small screens (< 375px) if multiple icon buttons overflow. Mitigation: test at 320px width. +2. **Low risk:** Missing `aria-label` would make icon buttons inaccessible. Mitigation: acceptance criteria require aria-label on every icon button. + +## Validation Architecture + +### Validation Strategy + +| Dimension | What to Validate | How | +|-----------|-----------------|-----| +| Visual | Icon buttons render on mobile, text on desktop | E2E viewport test or manual check | +| Accessibility | All icon buttons have aria-label | Grep for aria-label on new button elements | +| Touch targets | Minimum 44px on mobile | CSS class inspection (min-w-[44px] min-h-[44px]) | +| Consistency | Same breakpoint (md:) across all pages | Grep for breakpoint usage | +| No regression | Desktop buttons unchanged | Visual comparison | + +## RESEARCH COMPLETE