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>
12 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 | 02 | execute | 1 |
|
true |
|
|
Purpose: Complete the mobile icon button rollout across all remaining detail pages. Also clean up inline SVGs on setup page by migrating to the project's LucideIcon component for consistency. Output: Modified setup detail and global item 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;
Available icon names needed:
- "plus" — Add Items button
- "globe" — Public/Private toggle
- "trash-2" — Delete Setup button
- "message-square-plus" — Add to Thread button (verify exists in lucide-react)
<read_first>
- src/client/routes/setups/$setupId.tsx (current action buttons at lines ~155-210, inline SVGs for plus and globe icons)
- src/client/lib/iconData.tsx (LucideIcon component — confirm import path)
- .planning/phases/31-mobile-polish/31-UI-SPEC.md (icon mapping and color contract) </read_first>
Step 1: Add LucideIcon import.
Add import { LucideIcon } from "../../lib/iconData"; at the top of the file (if not already present).
Step 2: Migrate inline SVGs to LucideIcon.
- Replace the inline plus SVG in the "Add Items" button (lines ~162-175) with
<LucideIcon name="plus" size={16} /> - Replace the inline globe SVG in the Public/Private toggle button (lines ~188-198) with
<LucideIcon name="globe" size={16} />
Step 3: Add responsive icon/text splitting to all action buttons.
Add Items button:
- Desktop:
<button className="hidden md:inline-flex items-center gap-2 px-4 py-2 bg-gray-700 hover:bg-gray-800 text-white text-sm font-medium rounded-lg transition-colors" ...><LucideIcon name="plus" size={16} />Add Items</button> - Mobile:
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 bg-gray-700 hover:bg-gray-800 text-white rounded-lg transition-colors" aria-label="Add Items" title="Add Items" ...><LucideIcon name="plus" size={16} /></button>
Public/Private toggle:
- Desktop:
<button className="hidden md:inline-flex items-center gap-1.5 px-3 py-2 text-sm font-medium rounded-lg transition-colors {conditional classes}" ...><LucideIcon name="globe" size={16} />{setup.isPublic ? "Public" : "Private"}</button> - Mobile:
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 rounded-lg transition-colors {conditional classes}" aria-label={setup.isPublic ? "Public" : "Private"} title={setup.isPublic ? "Public" : "Private"} ...><LucideIcon name="globe" size={16} /></button> - Keep the conditional color classes:
text-green-700 bg-green-50 hover:bg-green-100when public,text-gray-500 bg-gray-50 hover:bg-gray-100when private.
Delete Setup button:
- Desktop:
<button className="hidden md:inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-red-600 bg-red-50 hover:bg-red-100 rounded-lg transition-colors" ...>Delete Setup</button> - Mobile:
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 text-red-600 bg-red-50 hover:bg-red-100 rounded-lg transition-colors" aria-label="Delete Setup" title="Delete Setup" ...><LucideIcon name="trash-2" size={16} /></button>
Keep all existing onClick handlers, disabled states, and conditional rendering logic. The flex-1 spacer between toggle and delete buttons remains.
Per D-01: Apply to setup detail page. Per D-02: Desktop text, mobile icons at md: breakpoint. Per D-03: Standard icon mapping — plus for Add, globe for toggle, trash-2 for Delete.
<acceptance_criteria>
$setupId.tsxcontainsimport { LucideIcon }orimport { LucideIconfrom iconData$setupId.tsxcontains<LucideIcon name="plus"(replacing inline plus SVG)$setupId.tsxcontains<LucideIcon name="globe"(replacing inline globe SVG)$setupId.tsxcontains<LucideIcon name="trash-2"for Delete Setup icon$setupId.tsxcontainsaria-label="Add Items"on an icon button$setupId.tsxcontainsaria-label="Delete Setup"on an icon button$setupId.tsxcontainsmin-w-[44px]for touch target sizing (at least 3 occurrences)$setupId.tsxcontains NO inline<svgelements (all migrated to LucideIcon)$setupId.tsxcontainshidden md:inline-flexon desktop text buttons </acceptance_criteria>
Setup detail page shows icon-only Add Items/Public toggle/Delete Setup buttons on mobile, full text buttons on desktop. Inline SVGs replaced with LucideIcon. All icon buttons have aria-label and 44px minimum touch targets.
Task 2: Add responsive icon buttons to global item detail page src/client/routes/global-items/$globalItemId.tsx<read_first>
- src/client/routes/global-items/$globalItemId.tsx (current action buttons at lines ~167-193)
- src/client/lib/iconData.tsx (LucideIcon component, verify "message-square-plus" icon exists in lucide-react)
- .planning/phases/31-mobile-polish/31-UI-SPEC.md (icon mapping and color contract) </read_first>
Step 1: Add LucideIcon import.
Add import { LucideIcon } from "../../lib/iconData"; at the top of the file (if not already present).
Step 2: Add responsive icon/text splitting to action buttons.
The action buttons section (flex gap-3 mb-6 containing "Add to Collection" and "Add to Thread") needs responsive variants:
Add to Collection button:
- Desktop:
<button className="hidden md:inline-flex items-center gap-2 bg-gray-700 text-white rounded-lg px-5 py-2.5 text-sm font-medium hover:bg-gray-800 transition-colors" ...>Add to Collection</button> - Mobile:
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2.5 bg-gray-700 text-white rounded-lg hover:bg-gray-800 transition-colors" aria-label="Add to Collection" title="Add to Collection" ...><LucideIcon name="plus" size={16} /></button>
Add to Thread button:
First, verify that "message-square-plus" exists in lucide-react. If it does not, use "message-square" instead. Check by running: grep -r "message-square-plus" node_modules/lucide-react/dist/ 2>/dev/null | head -1
- Desktop:
<button className="hidden md:inline-flex items-center gap-2 bg-white text-gray-700 border border-gray-200 rounded-lg px-5 py-2.5 text-sm font-medium hover:bg-gray-50 transition-colors" ...>Add to Thread</button> - Mobile:
<button className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2.5 bg-white text-gray-700 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors" aria-label="Add to Thread" title="Add to Thread" ...><LucideIcon name="message-square-plus" size={16} /></button>
Keep all existing onClick handlers (including the auth check that calls openAuthPrompt() for unauthenticated users).
Per D-01: Apply to catalog/global item detail page. Per D-02: Desktop text, mobile icons at md: breakpoint. Per D-03: Standard icon mapping — plus for Add to Collection, message-square-plus for Add to Thread.
<acceptance_criteria>
$globalItemId.tsxcontainsimport { LucideIcon }from iconData$globalItemId.tsxcontains<LucideIcon name="plus"for Add to Collection icon$globalItemId.tsxcontains<LucideIcon name="message-squarefor Add to Thread icon$globalItemId.tsxcontainsaria-label="Add to Collection"on an icon button$globalItemId.tsxcontainsaria-label="Add to Thread"on an icon button$globalItemId.tsxcontainsmin-w-[44px]for touch target sizing (at least 2 occurrences)$globalItemId.tsxcontainshidden md:inline-flexon desktop text buttons (at least 2 occurrences) </acceptance_criteria>
Global item detail page shows icon-only Add to Collection/Add to Thread buttons on mobile, full text 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-02 | 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>
- Setup detail page renders icon-only Add Items/Public toggle/Delete Setup buttons on mobile
- Global item detail page renders icon-only Add to Collection/Add to Thread buttons on mobile
- Desktop rendering unchanged (text buttons with optional icons)
- Setup page inline SVGs fully replaced with LucideIcon component
- 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 across both pages </success_criteria>