# Phase 20.1.1: Notes History Popover + Recipient Detail Sidebar - Context

**Gathered:** 2026-04-15
**Status:** Ready for planning

<domain>
## Phase Boundary

Repurpose the card's (i) button to open a scrollable ww-note history popover with an inline new-note composer; remove the note row from the card face and enlarge product squares to fill the freed space; relocate the existing Rx/Purpose/Vision summary content into a new recipient-detail sidebar (styled like `product-detail.slint`) accessed from the Recipients tab.

**In scope:**
- (i) button repurposed to open a notes history popover
- Scrollable ww-note history (read path) + new-note composer (write path, via pending_edit)
- Removal of the Row 5 note preview/inline editor from the card face
- Enlarging product squares proportionally on the card face
- New recipient-detail sidebar in the Recipients tab (Rx/Purpose/Vision + contact fields)
- Dashboard card name-click navigates to the Recipients tab and selects that recipient
- Deletion of the now-dead `summary-popup` and its wiring from `card.slint`

**Out of scope (deferred):**
- Editing or deleting existing notes (append-only)
- Per-note pending/sync indicators (notes look identical regardless of flush state)
- ww-recipient GH Issues link on the sidebar (placeholder only; real link waits for a future phase that introduces ww-recipient issues)
- Any other recipient-tab layout changes beyond selection-opens-sidebar

</domain>

<decisions>
## Implementation Decisions

### (i) Button & Notes Popover
- **D-01:** The (i) button (`info-icon-rect` in `card.slint:166-201`) is repurposed to open a new notes-history popover. It no longer opens `summary-popup`.
- **D-02:** The notes popover is a `PopupWindow` anchored to the (i) button, matching the current `summary-popup` positioning pattern. Closes on outside click / Esc / explicit close.
- **D-03:** Popover has a fixed height with internal scrolling. Empty state shows a "No notes yet" placeholder. No lazy-load — all notes for the card load up front.
- **D-04:** Notes sort order: newest-first at the top, scroll down for older notes.
- **D-05:** Each note row shows: author (GH handle) + relative timestamp (e.g. "2h ago"). Hover/tooltip reveals absolute datetime.
- **D-06:** Notes are append-only. No edit, no delete in this phase.

### New-Note Composer
- **D-07:** Composer lives at the top of the popover. When empty/idle it collapses into an "Add note" button; clicking expands it into a multi-line textbox.
- **D-08:** Submit mechanic: **Ctrl+Enter submits, Enter inserts a newline.** An explicit Send button is also present while the composer is expanded.
- **D-09:** Submission is optimistic — the new note appears at the top of the history instantly and the composer collapses back to the button. No visible pending indicator; pending and confirmed notes are indistinguishable in the UI.
- **D-10:** Failure surfaces only via the existing toast/error pipeline (no inline error UI in the popover).

### Notes Data Source & Sync
- **D-11:** Read path: SQLite is the source of truth, per DATA-FLOW.md. Opening the popover **also** triggers a targeted GH Issues fetch for this card's ww-note history to catch updates between full sync cycles. The fetch updates SQLite; the popover re-renders from SQLite.
- **D-12:** Write path: new notes are queued through the existing `pending_edit` mechanism (same pattern as other GH-bound writes). The flusher posts them to GH Issues on its normal cadence. No blocking UI.
- **D-13:** Offline behavior: posting a note while offline is allowed. The note lives in `pending_edit` and appears in the history; the flusher retries when connectivity returns. This matches the Phase 20 offline-first model.

### Card Face Reclamation
- **D-14:** The Row 5 note preview + inline editor block (`card.slint:557-666`) is removed entirely, including the stale "Row 6: Missing label — suppressed" comment. The `note-preview`, `editing-note`, `note-draft` properties and `save-note` callback on `RecipientCard` go with it (verify no other consumers first).
- **D-15:** The freed vertical space is spent by growing the product squares **proportionally, same count**. Card height stays the same. No change to the product grid's column count. Product-related text sizes are left at their current Typography values unless the visual balance demands a bump (Claude's discretion).

### Recipient-Detail Sidebar (new)
- **D-16:** The existing `summary-popup` (Rx/Purpose/Vision/Recipient Products) is **deleted** from `card.slint`. Its content moves into a new recipient-detail sidebar modeled on `product-detail.slint`.
- **D-17:** Sidebar layout: avatar at top, recipient name beside avatar in large font. Below: Purpose, Vision Rx (OD/OS with inline edit + Copy Rx), Discord username (editable), Shopify email, link to Shopify customer profile, and a placeholder link for the future ww-recipient issue (rendered only when a URL is wired in a later phase — no dead link UX now).
- **D-18:** Sidebar lives in the Recipients tab only. It does NOT appear on the main dashboard.
- **D-19:** Selection model:
  - In the Recipients tab, clicking any recipient tile opens/switches the sidebar to that recipient.
  - On the main dashboard, clicking a card's recipient name **navigates to the Recipients tab and auto-selects that recipient** (which opens the sidebar there). It does not open any sidebar from within the dashboard.
- **D-20:** Dismissal and edit affordances match `product-detail.slint` exactly (same open/close animation, X/click-outside/Esc, same inline-edit patterns). No new UX invented.

### Claude's Discretion
- Exact popover dimensions (width/height) — match visual weight of current `summary-popup` unless scrolling demands more.
- Exact size scaling factor for enlarged product squares — derive from the freed vertical pixel budget; keep the card's outer dimensions unchanged.
- Whether product-related text sizes need a minor bump for visual balance with the larger squares.
- Exact wire-up pattern for the targeted per-card GH Issues refresh on popover open (new method on the issues client vs. reusing an existing sync primitive).
- Whether the name-click-navigates-to-Recipients behavior needs a new callback on `RecipientCard` or can piggyback on existing navigation wiring.
- How the optimistic note is represented in the in-memory model before the flusher confirms (likely a `pending_edit` row that the read layer unions with SQLite rows).

</decisions>

<canonical_refs>
## Canonical References

**Downstream agents MUST read these before planning or implementing.**

### Data Architecture (MANDATORY per CLAUDE.md)
- `.planning/DATA-FLOW.md` — Authoritative data-entity + sync-direction reference. Notes are GH-Issues-of-record; SQLite is the app's single read source; pending_edit mediates writes.
- `code_tips/SQLITE_TIPS.md` — SQLite gotchas that apply to the read path.
- `code_tips/` (entire folder) — Slint and SQLite lessons; read before modifying UI or storage.

### UI Components (primary modification targets)
- `crates/app/ui/card.slint` — `RecipientCard`: info-icon (lines 166-201), summary-popup (~line 1011), note row (lines 557-666), Row 6 comment (line 666). This is the bulk of the card-side change.
- `crates/app/ui/product-detail.slint` — Template for the new recipient-detail sidebar (layout, open/close animation, inline-edit patterns).
- `crates/app/ui/dashboard.slint` — Tab switching / Recipients tab wiring (name-click navigation lands here).
- `crates/app/ui/option-grid.slint` — Recipients tab tile grid; tile selection now opens the recipient-detail sidebar.
- `crates/app/ui/tokens.slint` — Typography + Colors for the popover and sidebar.

### Data Layer & Sync
- `crates/app/src/live_client.rs` — Sync pipeline; targeted per-card ww-note refresh likely hooks in here.
- `crates/integrations/src/github/issues_client.rs` — GH Issues client; ww-note read/write lives here.
- `crates/service/src/db/sqlite.rs` — SqliteStore; notes table and `pending_edit` are defined/queried here.
- `crates/service/src/db/migrations/V001__initial_schema.sql` — Confirms current notes schema; any additions would need a new migration.
- `crates/app/src/dashboard/view_model.rs` — View-model surface that the Slint UI binds to; composer submit + history load both flow through here.

### Prior Phase Context (decisions that carry forward)
- `.planning/phases/20-offline-mode-hardening/20-CONTEXT.md` — Offline-first model, pending_edit queue, flusher cadence (D-13 relies on this).
- `.planning/phases/20.1-ui-polish-and-bug-fixes/20.1-CONTEXT.md` — Avatar/font sizing (D-01..D-05 there), product image pipeline (D-06..D-08 there). The larger product squares in this phase build on the image-fit-contain decision.
- `.planning/phases/16-gh-project-new-columns-ingestion/` — Purpose/Vision Rx/Recipient Products ingestion — the data the new sidebar surfaces.
- `.planning/phases/16.1-discord-username-inline-editing-in-summary-popover-with-gh-project-write-back-discord-user-profile-image-fetching-and-avatar-caching/` — Discord username inline-edit pattern (carry the editor into the sidebar).

</canonical_refs>

<code_context>
## Existing Code Insights

### Reusable Assets
- **`product-detail.slint`** — Direct template for the new recipient-detail sidebar. Same tab-scoped sidebar, same dismissal model.
- **`PopupWindow` + anchor pattern** — Already used for `summary-popup` (`card.slint:1011`) and `card-menu` (`card.slint:690`). The notes popover follows the same pattern anchored to the (i) button.
- **`pending_edit` pipeline** — Established write-path used for GH-bound mutations. New notes plug into it without new infrastructure.
- **Discord inline-edit on summary-popup** (Phase 16.1) — The edit affordance pattern is already built; port it into the sidebar.
- **Copy-Rx button** — Already on summary-popup; moves verbatim to sidebar.

### Established Patterns
- **SQLite-only reads** — CLAUDE.md rule; the popover's read path must obey (D-11).
- **Optimistic UI + background flush** — Matches the user's memory `feedback_async_app_model.md` ("SQLite is source of truth, flusher handles remote sync, never block UI").
- **Slint PopupWindow quirks** — Per `code_tips/`, PopupWindow re-inits on show; do NOT store scroll position or composer draft inside the popup itself (mirror the `summary-popup` pattern where state lives on the parent `RecipientCard`).

### Integration Points
- (i) button TouchArea callback (`card.slint:188-201`) — swap `summary-popup.show()` for the new notes-popover trigger.
- Card name text / touch area — new callback fires tab-switch + recipient-selection.
- Recipients option-grid tile click — new callback selects the tile and shows the sidebar.
- view_model — gains a `notes_history(card_id)` loader and a `post_note(card_id, text)` mutator; both likely already have partial analogs.

</code_context>

<specifics>
## Specific Ideas

- Composer UX model is explicitly chat-app-like for Ctrl+Enter, but inverted visually (newest at top, composer at top) — this mirrors GitHub Issues rather than Slack/Discord, which fits since the backing store is GH Issues comments.
- Sidebar header styling: avatar + large name side-by-side is user-specified — do not stack vertically.
- Shopify profile link and ww-recipient issue link are user-specified — render them as links (not buttons). The ww-recipient link is a placeholder for a future phase; conditional-render only when the URL exists so no dead link ships now.
- Name-click-navigates-to-tab is a specific user requirement — do NOT add a shortcut that opens the sidebar inside the dashboard.

</specifics>

<deferred>
## Deferred Ideas

- **Edit / delete of existing notes** — rejected for this phase (append-only). Future phase if needed.
- **Per-note pending/sync indicator** — rejected; failures go through toasts. Revisit if users report confusion.
- **ww-recipient GH Issues integration** — the sidebar reserves a slot for this link, but the actual ww-recipient issue type + wiring is a separate future phase.
- **Lazy-loading large note histories** — not needed now; revisit if any card accumulates enough notes to make the initial load slow.
- **Showing more product squares on the card (increased density)** — user chose "grow squares, same count" instead. Retained as an alternative if visual testing reveals the grown squares don't read well.

### Reviewed Todos (not folded)
(None reviewed for this phase — no cross-reference matches surfaced during load.)

</deferred>

---

*Phase: 20.1.1-change-the-i-button-on-cards-to-show-a-scrollable-history-of*
*Context gathered: 2026-04-15*
