Files
GearBox/.planning/milestones/v2.2-phases/31-mobile-polish/31-02-PLAN.md
Jean-Luc Makiola 2853477a75
All checks were successful
CI / ci (push) Successful in 1m15s
CI / e2e (push) Has been skipped
CI / deploy (push) Has been skipped
chore: archive v2.2 User Experience Polish milestone
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>
2026-04-13 16:00:35 +02:00

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
src/client/routes/setups/$setupId.tsx
src/client/routes/global-items/$globalItemId.tsx
true
D-01
D-02
D-03
D-04
truths artifacts key_links
Setup detail shows icon-only action buttons below md breakpoint
Setup detail shows text action buttons at md and above
Global item detail shows icon-only action buttons below md breakpoint
Global item 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
Setup page inline SVGs replaced with LucideIcon component
src/client/routes/setups/$setupId.tsx (modified)
src/client/routes/global-items/$globalItemId.tsx (modified)
LucideIcon component used for all icons (not inline SVGs)
md
breakpoint matches BottomTabBar responsive pattern
Add responsive icon-based action buttons to setup detail and global item detail pages, and migrate setup page inline SVGs to LucideIcon.

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)
Task 1: Add responsive icon buttons to setup detail page and migrate inline SVGs to LucideIcon src/client/routes/setups/$setupId.tsx

<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>
In src/client/routes/setups/$setupId.tsx:

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-100 when public, text-gray-500 bg-gray-50 hover:bg-gray-100 when 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.tsx contains import { LucideIcon } or import { LucideIcon from iconData
  • $setupId.tsx contains <LucideIcon name="plus" (replacing inline plus SVG)
  • $setupId.tsx contains <LucideIcon name="globe" (replacing inline globe SVG)
  • $setupId.tsx contains <LucideIcon name="trash-2" for Delete Setup icon
  • $setupId.tsx contains aria-label="Add Items" on an icon button
  • $setupId.tsx contains aria-label="Delete Setup" on an icon button
  • $setupId.tsx contains min-w-[44px] for touch target sizing (at least 3 occurrences)
  • $setupId.tsx contains NO inline <svg elements (all migrated to LucideIcon)
  • $setupId.tsx contains hidden md:inline-flex on desktop text buttons </acceptance_criteria>
grep -c "aria-label" src/client/routes/setups/\$setupId.tsx | grep -q "[3-9]" && grep -c "LucideIcon" src/client/routes/setups/\$setupId.tsx | grep -q "[3-9]" && ! grep -q "

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>
In src/client/routes/global-items/$globalItemId.tsx:

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.tsx contains import { LucideIcon } from iconData
  • $globalItemId.tsx contains <LucideIcon name="plus" for Add to Collection icon
  • $globalItemId.tsx contains <LucideIcon name="message-square for Add to Thread icon
  • $globalItemId.tsx contains aria-label="Add to Collection" on an icon button
  • $globalItemId.tsx contains aria-label="Add to Thread" on an icon button
  • $globalItemId.tsx contains min-w-[44px] for touch target sizing (at least 2 occurrences)
  • $globalItemId.tsx contains hidden md:inline-flex on desktop text buttons (at least 2 occurrences) </acceptance_criteria>
grep -c "aria-label" src/client/routes/global-items/\$globalItemId.tsx | grep -q "[2-9]" && grep -c "LucideIcon" src/client/routes/global-items/\$globalItemId.tsx | grep -q "[2-9]" && echo "PASS" || echo "FAIL"

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>
- `bun run lint` passes with no errors in modified files - `bun test` passes (no test regressions) - Manual: Open setup detail at mobile viewport (< 768px) — see icon-only buttons - Manual: Open global item detail at mobile viewport — see icon-only buttons - Manual: Open both pages at desktop viewport — see text buttons - No inline `

<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>
After completion, create `.planning/phases/31-mobile-polish/31-02-SUMMARY.md`