--- id: CE-WP-0010 type: workplan title: "Annotate & Attributes UX — labels, filters, layout, evidence connectors" domain: infotech repo: citation-evidence repo_id: a677c189-b4e2-4f2a-9e48-faa482c277e6 topic_slug: citation_evidence_mvp topic_id: cee7bedf-2b48-46ef-8601-006474f2ad7a status: finished owner: codex created: "2026-07-30" updated: "2026-07-30" depends_on_workplan: CE-WP-0009 planning_order: 10 planning_priority: high spec_refs: - wiki/ProductRequirementsDocument.md - workplans/CE-WP-0003-form-binding-visual-guide.md - workplans/CE-WP-0007-capture-view-polish.md - docs/decisions/ADR-0004-pdf-viewer-library.md state_hub_workstream_id: "e03c5d0c-36f9-49ef-8c6d-1dafe1fc781b" --- # CE-WP-0010 — Annotate & Attributes UX Follow-on UX optimization after the MVP capture/review loop (CE-WP-0002…0009) and successful manual document review. Aligns mode labels with the product vocabulary (**Annotate** / **Capture**), treats structured capture as **Attributes** (not “forms”), adds list filters, reshapes Capture to keep the Evidence column, and draws connector lines from evidence cards to in-document citations. ## User requirements (locked) 1. **Rename tab “Review” → “Annotate”.** User-facing mode label only; hash mode id may stay `review` unless a cheap rename is risk-free. 2. **Evidence → citation connector lines.** When an evidence card is active (or focused for linking), draw a visual guide from the card to the highlighted citation in the document — same family of UX as the field ↔ evidence guide introduced in CE-WP-0003 / polished in CE-WP-0007 (grey, thin lines). 3. **Evidence list filter.** Next to the Evidence column caption, a text field filters which evidence cards are shown. Filtering **starts at 3 characters**; match is case-insensitive against **any textual content** of the card (at minimum: quote/excerpt, commentary, and other visible card text). Below 3 characters, show the full list. 4. **Capture layout keeps Evidence; Attributes become a new right column.** Switching to Capture must **not** replace or bury the Evidence column. Target column order: ``` Collection | Viewer | Evidence | Attributes ``` Do **not** show the bottom EvidenceStrip / evidence cards under the page. 5. **Caption “Demo evidence-backed form” → “Attributes”.** 6. **Drop the word “form” from the UI.** Captured structured data are **attributes** with a **key**, a **value**, and a **type**. Internal code names (`FormsApp`, `form-field`, persistence keys) may remain until a later cleanup; user-visible copy must not say “form”. 7. **Type next to key.** Render as `Key (type)` — type in parentheses to the right of the attribute key/label (e.g. `Summary (textarea)`, `Key deadline (date)`). 8. **Attributes list filter.** Next to the “Attributes” caption, a text field with the same ≥3-character rule as Evidence, matching any of the attribute’s visible content (key, type, value). ## Goals 1. Clearer mode naming: Annotate (mark citations) vs Capture (bind to attributes). 2. Faster scanning of long evidence / attribute lists via live filters. 3. Capture view remains document-centric with Evidence always visible. 4. Connector lines make the active citation’s relationship to the card obvious. 5. Consistent “Attributes” vocabulary end-to-end in the shell UI. ## Non-goals - Renaming internal packages, hash modes, or engine `targetType: "form-field"` (track as follow-up if desired). - Server-side search / full-text index. - Changing export formats or ZIP session schema. - Multi-document filter scopes beyond the active document’s evidence list (keep current sidebar scoping unless already multi-doc). ## Code anchors (current) | Area | Where | |------|--------| | Mode tabs (“Review” / “Capture”) | `src/app/App.tsx` | | Annotate layout | `src/app/ReviewLayout.tsx` → `CollectionList` + `ViewerShell` + `EvidenceSidebar` | | Capture layout + bottom strip | `src/app/forms/FormsApp.tsx` | | Demo schema title | `src/app/forms/demo-schema.ts` (`DEMO_SCHEMA.title`) | | Attribute field renderer | `@binder/FormRenderer` (`../evidence-binder/src/FormRenderer.tsx`) | | Evidence sidebar caption / cards | `@work/EvidenceSidebar` (`../citation-work/src/work/EvidenceSidebar.tsx`) | | Existing visual guide | `@binder` Overlay / rect registry (CE-WP-0003-T07) | | Highlight rect bridge | `src/app/forms/HighlightRectBridge.tsx` | ## Dependency order ``` T01 (Annotate label) T02 (Attributes terminology + key (type) + demo title) ── parallel with T01 T03 (Evidence filter) T04 (Attributes filter) — after T02 caption exists T05 (Capture 4-column layout; drop bottom strip) ── after T02/T03 T06 (Evidence card → citation connector lines) ── after T05 (stable card rects) T07 (tests + copy audit) ``` --- ## T01 — Rename mode tab “Review” → “Annotate” ```task id: CE-WP-0010-T01 status: done priority: high state_hub_task_id: "acacc281-7cc3-4833-a123-593494cafe24" ``` **Change:** In the session top bar tab list (`src/app/App.tsx`), set the label for the review mode tab from `"Review"` to `"Annotate"`. **Also update** any user-visible strings that still say “Review mode” in empty states, aria-labels, or session menu help if present. Keep `mode: "review"` in the hash router unless renaming is trivial and tests are updated in the same task. **Acceptance:** - Top bar shows **Annotate** | **Capture**. - Deep links and session restore still open the annotate layout. - No user-visible “Review” mode label remains in the shell. --- ## T02 — Attributes terminology, demo title, key (type) ```task id: CE-WP-0010-T02 status: done priority: high state_hub_task_id: "f8538031-3916-4f3b-a66c-2a5fd1d575f7" ``` **UI copy (drop “form”):** - `DEMO_SCHEMA.title`: `"Demo evidence-backed form"` → `"Attributes"`. - Column / pane captions: **Attributes** (not “Form”, “Form pane”, “Demo form”, “evidence-backed form”). - Buttons/actions: prefer “Add attribute” over “Add Field” where the string is user-visible; keep technical test ids stable if needed. - Aria-labels and toasts: replace “form field” with “attribute” in user-facing text. **Key + type display (req 7):** - Each attribute row shows the key/label with the type in parentheses to its right, e.g. `Summary (textarea)`. - Implementation likely in `FormRenderer` / field header markup in `evidence-binder`; ensure add/edit still uses a clear type control. **Acceptance:** - Capture right column caption is **Attributes**. - No user-visible string contains the word “form” / “Form” in the app shell (case-insensitive copy audit of rendered UI strings). - Attribute headers render `Key (type)`. --- ## T03 — Evidence column filter (≥3 characters) ```task id: CE-WP-0010-T03 status: done priority: high state_hub_task_id: "5ba0e6dd-e2c9-4167-87fb-2ac7a7d81933" ``` Next to the **Evidence** caption in the right column of Annotate (and the Evidence column once Capture shares it — see T05), add a single-line text input. **Behaviour:** | Input length | Result | |--------------|--------| | 0–2 chars | Show all evidence cards (no filter) | | ≥3 chars | Show only cards whose **any** content matches the pattern | **Match surface (minimum):** quote / excerpt text, commentary / notes, and other visible card body text. Matching is case-insensitive substring (default); document if a different matcher is chosen. **UX:** placeholder like `Filter…`; clearing the field restores the full list; filter state may be local to the component (no persistence required for MVP). **Acceptance:** - With 2 characters typed, list unchanged. - With 3+ characters, only matching cards remain. - Empty match set shows an empty list (or a quiet “No matches” affordance). - Filter UI sits next to the Evidence caption, not buried in a menu. --- ## T04 — Attributes column filter (≥3 characters) ```task id: CE-WP-0010-T04 status: done priority: high depends_on: [T02] state_hub_task_id: "3ca351b4-a039-48ad-a2a1-d95cc202b04f" ``` Same interaction model as T03, next to the **Attributes** caption: - ≥3 characters → filter attributes by key, type, and value (any match). - 0–2 characters → show all attributes. **Acceptance:** - Symmetric behaviour to the Evidence filter. - Add-attribute control remains available when the filter is active (filtered-out rows hide; add flow still works). --- ## T05 — Capture layout: keep Evidence; Attributes as new right column ```task id: CE-WP-0010-T05 status: done priority: critical depends_on: [T02, T03] state_hub_task_id: "45e4a981-9985-49cd-bdbf-4ce8e29ae243" ``` **Problem:** Capture mode currently uses Collection | Viewer | FormPane with an **EvidenceStrip along the bottom**, which hides the full Evidence sidebar experience and duplicates cards under the page. **Target layout:** ``` ┌────────────┬──────────────┬──────────┬────────────┐ │ Collection │ ViewerShell │ Evidence │ Attributes │ └────────────┴──────────────┴──────────┴────────────┘ ``` **Requirements:** 1. Evidence column is the **same sidebar component** (or shared shell) used in Annotate — cards, export, edit, and T03 filter included. 2. Attributes column is the structured capture pane (former form pane) only — field/attribute editors, link chips, add/edit attribute. 3. **Remove** the bottom `EvidenceStrip` (and any layout that pins evidence under the viewer). Linking continues via field-focus + click evidence card in the Evidence column (CE-WP-0007 focus-gated linking). 4. Switching Annotate ↔ Capture preserves session documents, evidence, and attribute state; only the Attributes column mounts/unmounts (or shows) as appropriate. 5. Visual guide for attribute ↔ evidence (existing) still works with the new geometry. **Likely approach:** - Compose Capture from `ReviewLayout`-style columns + an Attributes pane, or lift a shared multi-column shell in `src/app/` that both modes use. - Drop `EvidenceStrip` from `FormsApp.tsx` once the sidebar is wired for linking. **Acceptance:** - Capture never shows a bottom evidence strip. - Evidence column visible and usable in both Annotate and Capture. - Attributes appear only in Capture, to the right of Evidence. - Linking attribute ↔ evidence still works without the strip. --- ## T06 — Connector lines: Evidence card → in-document citation ```task id: CE-WP-0010-T06 status: done priority: high depends_on: [T05] state_hub_task_id: "3451fe43-2909-4bf6-aa7c-72805239245b" ``` **Behaviour:** When an evidence item is active, draw a guide line from the evidence **card** (sidebar) to the **highlighted citation** in the viewer (text layer / highlight rect), analogous to the attribute ↔ evidence guide. **Style:** Match CE-WP-0007 softer guide lines (grey, thin); reuse the rect-registry + Overlay stack from CE-WP-0003 where possible. **Modes:** - **Annotate:** card ↔ highlight (primary). - **Capture:** keep attribute ↔ card ↔ highlight as today; ensure card ↔ highlight still reads clearly when an attribute is not focused. **Implementation notes:** - Evidence cards must publish rects (`kind` appropriate for registry). - Highlight rects already bridge via `HighlightRectBridge` / viewer adapter. - Re-render on scroll, resize, sidebar scroll, and active-evidence change. - No line when the active highlight rect is unavailable (fail soft). **Acceptance:** - Activate an evidence card → a connector appears from card to citation. - Scroll viewer or sidebar → line tracks (or clears cleanly if off-screen policy is defined). - Unlink / deselect clears the line. - Annotate mode has this without requiring Capture. --- ## T07 — Tests, copy audit, docs touch-up ```task id: CE-WP-0010-T07 status: done priority: medium depends_on: [T01, T02, T03, T04, T05, T06] state_hub_task_id: "cc6802be-c910-4b5b-aa36-0ba970aff4c4" ``` **Tests (prefer DOM / integration where layout matters):** 1. Tab label **Annotate** is present; **Review** is not. 2. Demo / column title **Attributes**; filter ≥3 chars hides non-matching attributes. 3. Evidence filter ≥3 chars hides non-matching cards; 2 chars does not. 4. Capture layout: Evidence column present; no bottom strip test id / region. 5. Connector: with mocked/published rects, Overlay includes a path/line for active evidence (extend existing visual-guide tests if present). 6. Attribute header shows `(type)` beside the key. **Copy audit:** ripgrep user-facing string literals under `src/app/`, `citation-work` work UI, and `evidence-binder` FormRenderer for `\b[Ff]orm\b` in UI strings; fix stragglers or document intentional internal-only uses. **Docs:** brief note in `docs/mvp-workplans-index.md` (or successor) that CE-WP-0010 is the post-MVP shell UX pass; optional one-line SCOPE/README mode naming if those still say “Review”. **Acceptance:** `pnpm test`, `pnpm lint`, and `pnpm typecheck` green; manual smoke of Annotate + Capture on a fixture PDF passes the locked requirements 1–8. --- ## Manual acceptance script (all requirements) 1. `pnpm dev` → open session → top bar shows **Annotate** | **Capture**. 2. Annotate: upload/fixture PDF → capture two evidence items with distinct commentary → filter Evidence with 2 chars (no change) → 3+ chars of one commentary (only that card) → clear filter. 3. Activate a card → grey connector to the highlighted passage; scroll keeps the association understandable. 4. Switch to **Capture** → Evidence column still visible with the same cards; **Attributes** column on the far right; **no** bottom evidence strip. 5. Attributes caption is **Attributes**; rows show `Key (type)`; filter works like Evidence. 6. Focus an attribute → click evidence → link + existing attribute guide still works. 7. No user-visible “form” / “Review” mode wording in the shell. --- ## Out of scope / follow-ups - Persist filter query strings across reloads. - Rename hash mode `review` → `annotate` and `forms` → `capture`. - Rename `FormsApp` / `form-field` target type in the engine. - Fuzzy / diacritic-insensitive search beyond simple substring. - Connector line animation or multi-card simultaneous guides.