Refine evidence UX: sidebar capture form, inline edit, click highlight

Significant UX iteration:

Visual palette
- Debug text-layer overlay flips from yellow to light grey so it no
  longer collides with the evidence highlight colour.
- New highlight-styles.css matches the sidebar's #fff8d6/#e0c050
  palette so a passage marked in the document and its sidebar card
  speak the same visual language.
- Active (focused) evidence: same fill, thick #b78b1c outline on both
  the highlight and the sidebar card. Library's red --scrolledTo
  box-shadow is suppressed.

Activation model
- Click an evidence card in the sidebar → activates that item +
  scrolls the viewer to the passage + thickens the borders (existing
  behaviour, now visually clearer).
- Click a highlight in the document → activates the evidence that
  owns that annotation. New `findByAnnotationId()` on EvidenceService
  is the reverse lookup. Wired through a new `onHighlightClicked`
  prop on PdfSpikeViewer + `activeAnnotationId` prop that drives the
  data-ce-active attribute on the highlight wrapper.

Inline edit
- Each evidence card has a ✎ button that flips the card into an
  inline form with the citation (quote) and commentary fields.
- Saving calls a new `AnnotationService.updateQuote()` +
  existing `EvidenceService.updateCommentary()`. The selectors are
  untouched, so the marked passage in the document stays put — the
  inline hint says so explicitly.
- New `AnnotationUpdated` event added to the engine event vocabulary
  (SharedContracts.md §4 updated).

Capture form placement
- The yellow "New annotation" toolbar that lived above the viewer is
  gone. A new InlineCaptureForm component is now slotted into the
  sidebar between the cards that bracket the new selection in
  document flow (sorted by page + y of the first PdfRectSelector).
  If the new selection is before all existing evidence it appears at
  the top; if after all of them, at the bottom.
- The legacy AnnotationToolbar.tsx is removed; the public surface
  re-exports `InlineCaptureForm` instead.

Test updates
- tests/integration/citation-card-export-e2e.dom.test.tsx: switched
  to the seed-session helper (matches the other E2Es) since the
  fixture-button click path is gone.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 22:57:48 +02:00
parent f0af8887d1
commit 430c0e124c
11 changed files with 640 additions and 247 deletions

View File

@@ -2,39 +2,34 @@
* Debug overlay for PDF text layer alignment.
*
* The text layer is normally invisible (`opacity: 0`) and selectable.
* When `.ce-debug-textlayer` is on a parent, every text span becomes a
* yellow highlight so it's obvious where text is selectable and where it
* When `.ce-debug-textlayer` is on a parent, every text node becomes a
* light grey box so it's obvious where text is selectable and where it
* isn't — useful for diagnosing OCR misalignment, scan-only PDFs, and
* text-layer shift caused by font fallbacks.
*
* Light grey was chosen so the debug overlay does not clash with the
* citation-yellow used for evidence highlights (see highlight-styles.css).
*
* Toggle via the "Debug text layer" entry in SessionMenu.
*/
.ce-debug-textlayer .textLayer {
outline: 2px dashed rgba(255, 0, 0, 0.5);
background: rgba(255, 0, 0, 0.05);
outline: 2px dashed rgba(120, 120, 120, 0.55);
background: rgba(120, 120, 120, 0.06);
}
/* PDF.js 4.x wraps marked content in nested spans/divs — cover every
descendant so the entire selectable area is visible regardless of how
the renderer nested things. */
.ce-debug-textlayer .textLayer * {
background: rgba(255, 220, 0, 0.45) !important;
color: rgba(0, 0, 100, 0.85) !important;
background: rgba(170, 170, 170, 0.4) !important;
color: rgba(40, 40, 40, 0.85) !important;
opacity: 1 !important;
outline: 1px solid rgba(0, 100, 255, 0.3);
outline: 1px solid rgba(100, 100, 100, 0.35);
}
/* Make the canvas-rendered layer dim so the text-layer overlay stands
/* Dim the canvas-rendered layer slightly so the debug overlay stands
out by contrast. */
.ce-debug-textlayer canvas {
opacity: 0.35;
}
/* Make any existing TextHighlight rectangles obvious even in debug
mode (the highlighter's own yellow gets washed out by our debug
yellow). */
.ce-debug-textlayer .TextHighlight__part {
background: rgba(0, 200, 0, 0.45) !important;
outline: 2px solid rgba(0, 120, 0, 0.7) !important;
opacity: 0.4;
}