---
phase: 09-item-note-crud-wiring
plan: 07
status: complete
started: 2026-03-20
completed: 2026-03-20
---

## Summary

Redesigned the card item area to show items as small squares with 2-letter initials on colored backgrounds. Hovering a square shows the full item name in a dynamic text label above the squares. Per-item X remove button appears on hover. Round + add button opens the lookup modal.

## Key Changes

### card.slint
- Replaced old pipe-separated text area, +/- action buttons, and Y/N confirm bar with item squares layout
- Each square: 36x36px, clipped inner Rectangle for initials/image, unclipped wrapper for X button overflow
- 8-color deterministic palette via `bg-color-index` conditional expression
- Dynamic hover label: per-square Text element positioned at label area with opaque background to occlude default text
- X remove button uses opacity toggle (not if-conditional) to prevent hover flicker
- Round + add button (36px diameter) positioned after last square
- Exported `ItemSquareData` struct from card.slint (imported by dashboard.slint)

### dashboard.slint
- Imports `ItemSquareData` from card.slint
- Added `item-display-label` field to CardData
- Changed `card-remove-single-item` callback from `(int, string)` to `(int, int)` for index-based removal
- Removed dead `confirm-remove-clicked` and `remove-item-clicked` wirings
- Bound `item-squares` and `item-display-label` from card data to RecipientCard

### lookup-modal.slint
- Auto-focus search TextInput when search view shown (init callback)
- Auto-focus display name TextInput when create form shown (init callback)

### main.rs
- `rebuild_item_squares` now computes `item_display_label` ("Item Name" or "Item Name +N")
- `on_card_remove_single_item` uses index-based removal from pipe-separated string (fixes duplicate item bug)
- Added `item_display_label` field to CardData and seed cards
- Called `apply_filters` after seed data `rebuild_item_squares` initialization (fixes squares not showing on load)

## Commits

| Hash | Message |
|------|---------|
| 608ec85 | feat(09-07): redesign RecipientCard item area with item squares and round add button |
| 73b43ce | feat(09-07): wire item-squares property and remove-single-item in dashboard.slint |
| 8f84558 | fix(09-07): resolve checkpoint feedback - item squares UI polish |

## Self-Check: PASSED

- [x] Items display as small squares with 2-letter initials on colored backgrounds
- [x] Hovering an item square shows full item name in dynamic label
- [x] Clicking per-item X removes only that item from the card
- [x] Round + add button appears, opens lookup modal on click
- [x] Lookup modal search field auto-focused on open
- [x] Create form display name field auto-focused
- [x] App compiles and tests pass

## Deviations

- Tooltip replaced with dynamic text label above squares (user feedback: tooltip was distracting, couldn't hover to click X)
- X button moved inside square corner instead of tooltip (user feedback: need to be able to click it)
- Used opacity toggle instead of if-conditional for X button (prevents hover flicker from z-order conflicts)
- Used index-based removal instead of name-based (user found duplicate items all got removed)
- Item squares use default cursor, not pointer (user feedback: pointer misleading when no click action)

## key-files

### created
- (none — all modifications to existing files)

### modified
- crates/app/ui/card.slint
- crates/app/ui/dashboard.slint
- crates/app/ui/lookup-modal.slint
- crates/app/src/main.rs
