---
phase: 20.1.1.1-phase-20-1-1-gap-closure-recipient-tab-sidebar-coexistence-n
plan: "01"
subsystem: ui
tags: [slint, card, notes-popover, hover, product-add]

requires:
  - phase: 20.1.1-change-the-i-button-on-cards-to-show-a-scrollable-history-of
    provides: notes popover structure, item-squares row layout, D-05 hover-reveal pattern

provides:
  - Notes popover with content-driven row heights (VerticalLayout in clipped Rectangle)
  - Product-add (+) button hidden by default, visible only on card hover
  - Product-add (+) button vertically centered in 80px item-squares row

affects: [20.1.1.1-06-validation, any plan reading card.slint notes list or add-button]

tech-stack:
  added: []
  patterns:
    - "VerticalLayout inside clipped Rectangle for content-driven list rows (not Flickable)"
    - "Passive card-level TouchArea (card-hover-zone) as first child for whole-card hover detection"
    - "if <hover-zone>.has-hover gate for hover-only UI elements"

key-files:
  created: []
  modified:
    - crates/app/ui/card.slint

key-decisions:
  - "Used VerticalLayout inside clipped Rectangle (not Flickable) per SLINT_TIPS.md — avoids bottom-align bug"
  - "card-hover-zone placed as first child in RecipientCard so later siblings win click events while hover still propagates"
  - "Outer + button wrapper is 80px tall to match item-square outer height; inner 44px circle at y=18px centers it"
  - "Removed opacity fade (0.6) entirely — button is simply absent when not hovered, not dimmed"

patterns-established:
  - "Card-hover-zone pattern: first-child passive TouchArea for whole-card has-hover without stealing clicks"
  - "Content-height note rows: VerticalLayout inside clipped Rectangle, no fixed height on row Rectangles"

requirements-completed: [D-04, D-11, D-12]

duration: 18min
completed: 2026-04-15
---

# Phase 20.1.1.1 Plan 01: card.slint UAT defect fixes Summary

**VerticalLayout content-driven notes rows replace fixed-56px list; product-add (+) button gated on card-hover-zone.has-hover and vertically centered in 80px item-squares row**

## Performance

- **Duration:** ~18 min
- **Started:** 2026-04-15T17:20:00Z
- **Completed:** 2026-04-15T17:39:51Z
- **Tasks:** 2
- **Files modified:** 1

## Accomplishments

- D-04: Notes popover rows now grow with content — `VerticalLayout` inside clipped `Rectangle` replaces the `y: idx * 60px, height: 56px` absolute-y pattern; wrapped text rows no longer bleed
- D-11: Product-add (+) button is invisible when card is not hovered — gated via `if card-hover-zone.has-hover`; opacity fade removed entirely
- D-12: (+) button outer wrapper is 80px (matches item-square outer height); inner 44px circle at `y: 18px` centers it precisely in the row

## Task Commits

Both tasks committed together (single file):

1. **Task 1 + Task 2: D-04 notes rows, D-11 hover gate, D-12 alignment** — `50b5738` (fix)

**Plan metadata:** (docs commit follows)

## Files Created/Modified

- `crates/app/ui/card.slint` — notes scroll area replaced with VerticalLayout pattern; card-hover-zone TouchArea added; add-button block replaced with hover-gated conditional

## Decisions Made

- Placed `card-hover-zone` as the FIRST child of RecipientCard so Slint's last-sibling-wins click priority means all existing TouchAreas (name-area, info-hover, dots-touch, sq-touch, add-btn-touch) still receive clicks normally. The hover-zone only provides `has-hover`.
- Removed the `opacity: 0.6` fade from the old add-button — with hover-gating in place, a dim-but-always-visible button is incorrect; the button is simply absent off-hover.
- Kept `note-row-hover` TouchArea inside the for-loop so D-05 hover-reveal of absolute datetime is preserved.

## Deviations from Plan

None — plan executed exactly as written. The plan's template used `root.card-add-item()` but the actual callback is `root.add-item-clicked()`; used the correct existing name (no deviation, just template mismatch in plan prose).

## Issues Encountered

- **Pre-existing build failures:** `cargo check` reports 17 pre-existing errors in `main.rs` (mismatched method names like `invoke_card_save_discord_username`) unrelated to this plan's changes. Verified by stashing our changes and confirming identical errors on the baseline commit. These are tracked for a future plan to fix.

## Known Stubs

None — no placeholder data or hardcoded stubs introduced.

## Threat Flags

None — no new network endpoints, auth paths, or external service calls added.

## Next Phase Readiness

- D-04, D-11, D-12 fixes are in `card.slint` and ready for BUGSWEEPER + visual validation in Plan 06.
- Pre-existing build failures in `main.rs` must be resolved before the app can be run for visual validation.

---

## Self-Check

- [x] `crates/app/ui/card.slint` modified — confirmed in git diff
- [x] Commit `50b5738` exists — `git log --oneline | grep 50b5738`
- [x] `y: idx * 60px` — 0 matches (old absolute stride gone)
- [x] `height: 56px` inside notes area — 0 matches (fixed row height gone)
- [x] `card-hover-zone :=` — 1 match
- [x] `if card-hover-zone.has-hover` — 1 match
- [x] `opacity: add-btn-touch.has-hover ? 1.0 : 0.6` — 0 matches (fade removed)
- [x] `root.add-item-clicked()` — 1 match (callback preserved)
- [x] `y: 18px` inside add-button block — 1 match (inner circle centered)
- [x] `close-policy: close-on-click-outside` — 1 match (parent contract preserved)

## Self-Check: PASSED

---
*Phase: 20.1.1.1-phase-20-1-1-gap-closure-recipient-tab-sidebar-coexistence-n*
*Completed: 2026-04-15*
