225 lines
10 KiB
Markdown
225 lines
10 KiB
Markdown
---
|
|
phase: 35-bug-fixes
|
|
plan: 03
|
|
type: execute
|
|
wave: 1
|
|
depends_on: []
|
|
files_modified:
|
|
- src/client/components/ItemCard.tsx
|
|
- src/client/components/FabMenu.tsx
|
|
- src/client/components/BottomTabBar.tsx
|
|
autonomous: true
|
|
requirements:
|
|
- FIX-05
|
|
|
|
must_haves:
|
|
truths:
|
|
- "ItemCard outer button shows cursor-pointer when linkTo is not null"
|
|
- "ItemCard outer button shows cursor-default when linkTo === null (existing correct behavior, preserved)"
|
|
- "FabMenu menu item buttons explicitly have cursor-pointer"
|
|
- "FabMenu main FAB button explicitly has cursor-pointer"
|
|
- "BottomTabBar anonymous tab buttons have cursor-pointer"
|
|
artifacts:
|
|
- path: "src/client/components/ItemCard.tsx"
|
|
provides: "ItemCard with correct conditional cursor"
|
|
contains: "cursor-pointer"
|
|
- path: "src/client/components/FabMenu.tsx"
|
|
provides: "FabMenu buttons with explicit cursor-pointer"
|
|
contains: "cursor-pointer"
|
|
- path: "src/client/components/BottomTabBar.tsx"
|
|
provides: "BottomTabBar buttons with cursor-pointer"
|
|
contains: "cursor-pointer"
|
|
key_links:
|
|
- from: "ItemCard outer button"
|
|
to: "cursor-pointer class"
|
|
via: "linkTo !== null conditional class"
|
|
pattern: "cursor-pointer.*hover:border-gray-200"
|
|
---
|
|
|
|
<objective>
|
|
Audit and fix cursor-pointer coverage across interactive elements. The Tailwind utility cursor-pointer must be explicitly applied to all clickable elements that currently lack it.
|
|
|
|
Purpose: Resolve FIX-05 — the pointer cursor must appear on hover over every interactive element to meet basic UX expectations.
|
|
Output: Updated ItemCard, FabMenu, BottomTabBar with explicit cursor-pointer.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
|
@$HOME/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/phases/35-bug-fixes/35-CONTEXT.md
|
|
@.planning/phases/35-bug-fixes/35-UI-SPEC.md
|
|
</context>
|
|
|
|
<interfaces>
|
|
<!-- Key contracts the executor needs. Extracted from codebase. -->
|
|
|
|
Current cursor state by component (from codebase audit):
|
|
|
|
ItemCard (src/client/components/ItemCard.tsx, line 76):
|
|
```tsx
|
|
// Current — missing cursor-pointer in the navigable case:
|
|
className={`relative w-full text-left bg-white rounded-xl border border-gray-100 transition-all overflow-hidden group ${
|
|
linkTo === null
|
|
? "cursor-default"
|
|
: "hover:border-gray-200 hover:shadow-sm" // ← cursor-pointer MISSING here
|
|
}`}
|
|
// Target — add cursor-pointer to the navigable case:
|
|
className={`relative w-full text-left bg-white rounded-xl border border-gray-100 transition-all overflow-hidden group ${
|
|
linkTo === null
|
|
? "cursor-default"
|
|
: "cursor-pointer hover:border-gray-200 hover:shadow-sm"
|
|
}`}
|
|
```
|
|
|
|
ItemCard action span buttons (lines 106, 138, 170): already have cursor-pointer — DO NOT CHANGE.
|
|
ClassificationBadge: already has cursor-pointer — DO NOT CHANGE.
|
|
CandidateCard action spans: already have cursor-pointer — DO NOT CHANGE.
|
|
|
|
FabMenu (src/client/components/FabMenu.tsx):
|
|
- Line 85: menu item `motion.button` className — `"flex items-center gap-3 bg-white shadow-lg rounded-full px-4 py-3 hover:bg-gray-50 transition-colors"` — missing cursor-pointer
|
|
- Line 108: main FAB `motion.button` className — `"fixed bottom-6 right-6 z-20 w-14 h-14 bg-gray-700 hover:bg-gray-800 text-white rounded-full shadow-lg hover:shadow-xl transition-colors flex items-center justify-center"` — missing cursor-pointer
|
|
|
|
BottomTabBar (src/client/components/BottomTabBar.tsx):
|
|
- Lines 68, 87, 97: `<button type="button">` wrappers — no explicit cursor-pointer class
|
|
- Link elements (lines 50, 60, 79): Links get pointer from browser default — add cursor-pointer explicitly for consistency
|
|
|
|
Already correct (no changes needed):
|
|
- StatusBadge: has cursor-pointer
|
|
- CategoryPicker: has cursor-pointer
|
|
- PublicSetupCard: has cursor-pointer
|
|
- CategoryFilterDropdown: has cursor-pointer
|
|
- CatalogSearchOverlay interactive items: has cursor-pointer where needed
|
|
- ImageUpload: has cursor-pointer
|
|
- ProfileSection avatar: has cursor-pointer
|
|
</interfaces>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Add cursor-pointer to ItemCard navigable case (FIX-05)</name>
|
|
<files>src/client/components/ItemCard.tsx</files>
|
|
<read_first>
|
|
- src/client/components/ItemCard.tsx (read the outer button element at line 73-77 to confirm the current conditional class string)
|
|
</read_first>
|
|
<action>
|
|
In src/client/components/ItemCard.tsx, update the outer `<button>` element's className conditional string (per D-11, D-12, UI-SPEC Cursor Contract).
|
|
|
|
Find the className on the outer button (line ~76):
|
|
```tsx
|
|
className={`relative w-full text-left bg-white rounded-xl border border-gray-100 transition-all overflow-hidden group ${linkTo === null ? "cursor-default" : "hover:border-gray-200 hover:shadow-sm"}`}
|
|
```
|
|
|
|
Change to:
|
|
```tsx
|
|
className={`relative w-full text-left bg-white rounded-xl border border-gray-100 transition-all overflow-hidden group ${linkTo === null ? "cursor-default" : "cursor-pointer hover:border-gray-200 hover:shadow-sm"}`}
|
|
```
|
|
|
|
The only change is adding `cursor-pointer ` before `hover:border-gray-200` in the non-null branch.
|
|
|
|
Do NOT change:
|
|
- The `cursor-default` branch (correct behavior when `linkTo === null`)
|
|
- Any action span buttons on the card (lines 106, 138, 170 — already have cursor-pointer)
|
|
</action>
|
|
<verify>
|
|
<automated>cd /home/jlmak/Projects/jlmak/GearBox && grep -n "cursor-pointer hover:border-gray-200" src/client/components/ItemCard.tsx</automated>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- `grep -n "cursor-pointer hover:border-gray-200" src/client/components/ItemCard.tsx` returns exactly one match on the outer button className
|
|
- `grep -n "cursor-default" src/client/components/ItemCard.tsx` still returns one match (the linkTo === null branch is preserved)
|
|
- `bun run lint` passes with no errors
|
|
</acceptance_criteria>
|
|
<done>ItemCard outer button shows cursor-pointer when linkTo is not null, and cursor-default when linkTo === null. Both branches are correctly covered.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Add cursor-pointer to FabMenu and BottomTabBar buttons (FIX-05)</name>
|
|
<files>
|
|
src/client/components/FabMenu.tsx,
|
|
src/client/components/BottomTabBar.tsx
|
|
</files>
|
|
<read_first>
|
|
- src/client/components/FabMenu.tsx (read fully — locate motion.button at lines 82-99 and 106-114)
|
|
- src/client/components/BottomTabBar.tsx (read fully — locate button elements at lines 68, 87, 97)
|
|
</read_first>
|
|
<action>
|
|
**FabMenu changes** (per D-12, UI-SPEC Cursor Contract §FAB menu items):
|
|
|
|
1. Menu item buttons (motion.button, currently line ~85) — add `cursor-pointer` to className:
|
|
Current: `"flex items-center gap-3 bg-white shadow-lg rounded-full px-4 py-3 hover:bg-gray-50 transition-colors"`
|
|
Target: `"flex items-center gap-3 bg-white shadow-lg rounded-full px-4 py-3 hover:bg-gray-50 transition-colors cursor-pointer"`
|
|
|
|
2. Main FAB button (motion.button, currently line ~108) — add `cursor-pointer` to className:
|
|
Current: `"fixed bottom-6 right-6 z-20 w-14 h-14 bg-gray-700 hover:bg-gray-800 text-white rounded-full shadow-lg hover:shadow-xl transition-colors flex items-center justify-center"`
|
|
Target: `"fixed bottom-6 right-6 z-20 w-14 h-14 bg-gray-700 hover:bg-gray-800 text-white rounded-full shadow-lg hover:shadow-xl transition-colors flex items-center justify-center cursor-pointer"`
|
|
|
|
**BottomTabBar changes** (per D-12, UI-SPEC Cursor Contract §All role="button" elements):
|
|
|
|
For all three `<button type="button">` elements (anonymous user collection tab at line ~68, anonymous setups tab at ~87, search tab at ~97), add `cursor-pointer` to each button element:
|
|
|
|
Line ~68:
|
|
```tsx
|
|
<button type="button" onClick={openAuthPrompt} className="cursor-pointer">
|
|
```
|
|
Line ~87:
|
|
```tsx
|
|
<button type="button" onClick={openAuthPrompt} className="cursor-pointer">
|
|
```
|
|
Line ~97:
|
|
```tsx
|
|
<button type="button" onClick={() => openCatalogSearch("collection")} className="cursor-pointer">
|
|
```
|
|
</action>
|
|
<verify>
|
|
<automated>cd /home/jlmak/Projects/jlmak/GearBox && grep -c "cursor-pointer" src/client/components/FabMenu.tsx src/client/components/BottomTabBar.tsx</automated>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- `grep -c "cursor-pointer" src/client/components/FabMenu.tsx` outputs `2` (menu items button + main FAB button)
|
|
- `grep -c "cursor-pointer" src/client/components/BottomTabBar.tsx` outputs `3` (one per anonymous button)
|
|
- `bun run lint` passes with no errors across both files
|
|
</acceptance_criteria>
|
|
<done>FabMenu menu item buttons and main FAB button have explicit cursor-pointer. BottomTabBar's three button elements each have cursor-pointer. All known interactive elements now have correct cursor behavior.</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<threat_model>
|
|
## Trust Boundaries
|
|
|
|
| Boundary | Description |
|
|
|----------|-------------|
|
|
| none | Pure CSS/class changes — no trust boundary implications |
|
|
|
|
## STRIDE Threat Register
|
|
|
|
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|
|
|-----------|----------|-----------|-------------|-----------------|
|
|
| T-35-04 | none | cursor-pointer audit | accept | CSS-only change. No logic, data flow, or auth boundary touched. No threat surface. |
|
|
</threat_model>
|
|
|
|
<verification>
|
|
After both tasks complete:
|
|
|
|
1. Open collection overview — hover over an item card (with linkTo set): cursor must be pointer
|
|
2. Hover over a card in a setup (linkTo === null): cursor must be default (not pointer) — preserved
|
|
3. Open FAB menu — hover over menu items and FAB button: cursor must be pointer
|
|
4. On mobile viewport (or DevTools mobile mode), hover/tap BottomTabBar anonymous tabs: buttons must show pointer
|
|
|
|
Run: `bun run lint` — zero errors
|
|
Run: `bun test` — all existing tests pass
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- ItemCard outer button has cursor-pointer in the non-null linkTo branch, cursor-default in the null branch
|
|
- FabMenu has cursor-pointer on both motion.button elements (menu items + FAB)
|
|
- BottomTabBar has cursor-pointer on all three button elements
|
|
- No previously-correct cursor-pointer usage is removed
|
|
- bun run lint passes with zero errors
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/35-bug-fixes/35-03-SUMMARY.md`
|
|
</output>
|