Phases 28-31 archived to milestones/v2.2-phases/ Requirements and roadmap snapshots archived to milestones/ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 31-mobile-polish | 01 | execute | 1 |
|
true |
|
|
Purpose: Replace text-label action buttons with icon-only buttons on mobile viewports (below md: breakpoint) for better mobile UX. Desktop retains full text buttons. Output: Modified item detail and candidate detail pages with responsive action buttons.
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/31-mobile-polish/31-CONTEXT.md @.planning/phases/31-mobile-polish/31-UI-SPEC.md@src/client/components/BottomTabBar.tsx @src/client/lib/iconData.tsx
From src/client/lib/iconData.tsx:
export function LucideIcon({ name, size, className, strokeWidth }: {
name: string;
size?: number;
className?: string;
strokeWidth?: number;
}): React.ReactElement;
From src/client/components/BottomTabBar.tsx:
// Responsive breakpoint reference: md:hidden (mobile), hidden md:flex (desktop)
<read_first>
- src/client/routes/items/$itemId.tsx (current action button implementation, lines ~189-213)
- src/client/components/BottomTabBar.tsx (responsive breakpoint pattern reference)
- src/client/lib/iconData.tsx (LucideIcon component API)
- .planning/phases/31-mobile-polish/31-UI-SPEC.md (icon mapping and color contract) </read_first>
For each button, create a paired desktop/mobile pattern:
Duplicate button:
- Desktop (hidden on mobile):
<button className="hidden md:inline-flex items-center gap-1.5 px-3 py-1.5 text-sm text-gray-500 hover:text-gray-700 hover:bg-gray-50 rounded-lg transition-colors" ...>Duplicate</button> - Mobile (hidden on desktop):
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 text-gray-500 hover:text-gray-700 hover:bg-gray-50 rounded-lg transition-colors" aria-label="Duplicate" title="Duplicate" ...><LucideIcon name="copy" size={16} /></button>
Delete/Remove button:
- Desktop:
<button className="hidden md:inline-flex items-center gap-1.5 px-3 py-1.5 text-sm text-red-400 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" ...>{isReference ? "Remove from Collection" : "Delete"}</button> - Mobile:
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 text-red-400 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={isReference ? "Remove from Collection" : "Delete"} title={isReference ? "Remove from Collection" : "Delete"} ...><LucideIcon name="trash-2" size={16} /></button>
Edit button:
- Desktop:
<button className="hidden md:inline-flex items-center gap-1.5 px-4 py-1.5 text-sm font-medium text-white bg-gray-700 hover:bg-gray-800 rounded-lg transition-colors" ...>Edit</button> - Mobile:
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 text-white bg-gray-700 hover:bg-gray-800 rounded-lg transition-colors" aria-label="Edit" title="Edit" ...><LucideIcon name="pencil" size={16} /></button>
Ensure LucideIcon is already imported (it is — check line ~8). Keep all existing onClick handlers and disabled states. The Cancel/Save buttons in edit mode remain unchanged (text buttons on all viewports).
Per D-01: Apply icon-based action buttons on mobile to item detail page. Per D-02: Desktop keeps text buttons, mobile switches to icons at md: breakpoint. Per D-03: Standard icon mapping — pencil for Edit, trash-2 for Delete, copy for Duplicate.
<acceptance_criteria>
$itemId.tsxcontainsaria-label="Duplicate"on an icon button$itemId.tsxcontainsaria-label="Edit"on an icon button withmd:hiddenclass$itemId.tsxcontains<LucideIcon name="copy"for Duplicate icon$itemId.tsxcontains<LucideIcon name="trash-2"for Delete icon$itemId.tsxcontains<LucideIcon name="pencil"for Edit icon$itemId.tsxcontainsmin-w-[44px]for touch target sizing$itemId.tsxcontainshidden md:inline-flexon desktop text buttons- Cancel and Save buttons in edit mode do NOT have
md:hiddenresponsive splitting </acceptance_criteria>
Item detail page shows icon-only Duplicate/Delete/Edit buttons on mobile, full text buttons on desktop. All icon buttons have aria-label and 44px minimum touch targets.
Task 2: Add responsive icon buttons to candidate detail page src/client/routes/threads/$threadId/candidates/$candidateId.tsx<read_first>
- src/client/routes/threads/$threadId/candidates/$candidateId.tsx (current action buttons — header Edit at line ~282, bottom actions at lines ~530-548)
- .planning/phases/31-mobile-polish/31-UI-SPEC.md (icon mapping and color contract) </read_first>
Location 1: Header Edit button (line ~282-289)
Currently shows <LucideIcon name="pencil" size={14} /> + "Edit" text. Split into:
- Desktop:
<button className="shrink-0 hidden md:inline-flex items-center gap-1.5 px-3 py-1.5 text-sm text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-lg transition-colors" ...><LucideIcon name="pencil" size={14} />Edit</button> - Mobile:
<button className="shrink-0 md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-lg transition-colors" aria-label="Edit" title="Edit" ...><LucideIcon name="pencil" size={16} /></button>
Location 2: Bottom action buttons (lines ~530-548) Currently shows "Pick as winner" with trophy icon and "Delete" with trash-2 icon. Split each:
Pick as Winner:
- Desktop:
<button className="hidden md:inline-flex items-center gap-1.5 px-4 py-2 bg-amber-50 hover:bg-amber-100 text-amber-700 text-sm font-medium rounded-lg transition-colors" ...><LucideIcon name="trophy" size={14} />Pick as winner</button> - Mobile:
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 bg-amber-50 hover:bg-amber-100 text-amber-700 rounded-lg transition-colors" aria-label="Pick as winner" title="Pick as winner" ...><LucideIcon name="trophy" size={16} /></button>
Delete:
- Desktop:
<button className="hidden md:inline-flex items-center gap-1.5 px-4 py-2 text-sm text-red-500 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" ...><LucideIcon name="trash-2" size={14} />Delete</button> - Mobile:
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 text-red-500 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label="Delete" title="Delete" ...><LucideIcon name="trash-2" size={16} /></button>
Keep all existing onClick handlers. The edit mode buttons (Cancel, Save) remain unchanged.
Per D-01: Apply to candidate detail page. Per D-02: Desktop text, mobile icons at md: breakpoint. Per D-03: Standard icon mapping — pencil for Edit, trash-2 for Delete, trophy for Pick as winner.
<acceptance_criteria>
$candidateId.tsxcontainsaria-label="Edit"on an icon button withmd:hidden$candidateId.tsxcontainsaria-label="Pick as winner"on an icon button$candidateId.tsxcontainsaria-label="Delete"on an icon button$candidateId.tsxcontainsmin-w-[44px]for touch target sizing (at least 3 occurrences)$candidateId.tsxcontainshidden md:inline-flexon desktop text buttons (at least 3 occurrences)- Edit mode Cancel/Save buttons do NOT have responsive splitting </acceptance_criteria>
Candidate detail page shows icon-only Edit/Pick as winner/Delete buttons on mobile, full text+icon buttons on desktop. All icon buttons have aria-label and 44px minimum touch targets.
<threat_model>
Trust Boundaries
No new trust boundaries introduced. This plan only modifies client-side rendering of existing buttons. No new API calls, no new data flows, no new authentication paths.
STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|---|---|---|---|---|
| T-31-01 | Information Disclosure | Icon buttons | accept | Icon buttons show same actions as existing text buttons — no new information exposed. aria-label text matches existing button text. |
| </threat_model> |
<success_criteria>
- Item detail page renders icon-only Duplicate/Delete/Edit buttons on mobile
- Candidate detail page renders icon-only Edit/Pick as winner/Delete buttons on mobile
- Desktop rendering unchanged (text buttons with optional icons)
- All icon buttons have aria-label for accessibility
- All icon buttons have min-w-[44px] min-h-[44px] for comfortable touch targets
- md: breakpoint used consistently (matching BottomTabBar pattern) </success_criteria>