---
phase: 31-mobile-polish
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- src/client/routes/items/$itemId.tsx
- src/client/routes/threads/$threadId/candidates/$candidateId.tsx
autonomous: true
requirements: [D-01, D-02, D-03, D-04]
must_haves:
truths:
- Item detail shows icon-only action buttons below md breakpoint
- Item detail shows text action buttons at md and above
- Candidate detail shows icon-only action buttons below md breakpoint
- Candidate detail shows text action buttons at md and above
- All icon-only buttons have aria-label attributes
- All icon-only buttons have minimum 44px touch targets
artifacts:
- src/client/routes/items/$itemId.tsx (modified)
- src/client/routes/threads/$threadId/candidates/$candidateId.tsx (modified)
key_links:
- LucideIcon component used for all icons (not inline SVGs)
- md: breakpoint matches BottomTabBar responsive pattern
---
Add responsive icon-based action buttons to item detail and candidate detail pages.
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.
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
@.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:
```typescript
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)
```
Task 1: Add responsive icon buttons to item detail pagesrc/client/routes/items/$itemId.tsx
- 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)
In src/client/routes/items/$itemId.tsx, modify the action button group (the `div` with `flex items-center gap-2` containing Duplicate, Delete, and Edit buttons, visible when `!isEditing`).
For each button, create a paired desktop/mobile pattern:
**Duplicate button:**
- Desktop (hidden on mobile): ``
- Mobile (hidden on desktop): ``
**Delete/Remove button:**
- Desktop: ``
- Mobile: ``
**Edit button:**
- Desktop: ``
- Mobile: ``
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.
- `$itemId.tsx` contains `aria-label="Duplicate"` on an icon button
- `$itemId.tsx` contains `aria-label="Edit"` on an icon button with `md:hidden` class
- `$itemId.tsx` contains `grep -c "aria-label" src/client/routes/items/\$itemId.tsx | grep -q "[3-9]" && grep -c "md:hidden" src/client/routes/items/\$itemId.tsx | grep -q "[3-9]" && echo "PASS" || echo "FAIL"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 pagesrc/client/routes/threads/$threadId/candidates/$candidateId.tsx
- 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)
In src/client/routes/threads/$threadId/candidates/$candidateId.tsx, modify action buttons in two locations:
**Location 1: Header Edit button (line ~282-289)**
Currently shows `` + "Edit" text. Split into:
- Desktop: ``
- Mobile: ``
**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: ``
- Mobile: ``
**Delete:**
- Desktop: ``
- Mobile: ``
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.
- `$candidateId.tsx` contains `aria-label="Edit"` on an icon button with `md:hidden`
- `$candidateId.tsx` contains `aria-label="Pick as winner"` on an icon button
- `$candidateId.tsx` contains `aria-label="Delete"` on an icon button
- `$candidateId.tsx` contains `min-w-[44px]` for touch target sizing (at least 3 occurrences)
- `$candidateId.tsx` contains `hidden md:inline-flex` on desktop text buttons (at least 3 occurrences)
- Edit mode Cancel/Save buttons do NOT have responsive splitting
grep -c "aria-label" src/client/routes/threads/\$threadId/candidates/\$candidateId.tsx | grep -q "[3-9]" && grep -c "md:hidden" src/client/routes/threads/\$threadId/candidates/\$candidateId.tsx | grep -q "[3-9]" && echo "PASS" || echo "FAIL"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.
## 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. |
- `bun run lint` passes with no errors in modified files
- `bun test` passes (no test regressions)
- Manual: Open item detail at mobile viewport (< 768px) — see icon-only buttons
- Manual: Open item detail at desktop viewport (>= 768px) — see text buttons
- Manual: Open candidate detail at mobile viewport — see icon-only buttons
- 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)