Unify capture/edit form, thicker active document border, layer-hide toggles
Three UX iterations rolled into one:
1. Unified evidence form
- New EvidenceFormBody is the single source for "citation +
commentary" editing. Both InlineCaptureForm (creating fresh
evidence from a selection) and the EvidenceCard edit mode render
this body with their own save/cancel labels + badge/helper text.
- The capture form now exposes the citation as an editable
textarea — pre-filled with the selection text — so the user can
refine a partial capture before saving without re-selecting.
- Old testid prefixes are unchanged for the inline-capture flow
(`inline-capture-quote/commentary/save/cancel`); edit-mode
testids are now `evidence-edit-<id>-{quote,commentary,save,cancel}`.
2. Active document card
- The blue background alone was the only "this is open" cue. Added
a 3px #0050b3 border (matching the evidence-card thick-border
pattern, but in the documents-are-blue palette) plus a
`data-active` attribute.
3. PDF layer-hide diagnostics
- New debug flags `hideCanvas`, `hideTextLayer`, `hideAnnotationLayer`,
`hideXfaLayer` — applied as `.ce-hide-<layer>` classes on the viewer
wrapper, each `display: none`-ing the matching PDF.js layer.
- SessionMenu groups the toggles under a "PDF diagnostics" header
with a new shared DebugCheckbox helper. The existing "Debug text
layer" highlight toggle now lives in the same group.
- Lets the user isolate stacking issues by elimination — e.g.
"hide text layer, can I now see the canvas content underneath?".
Tests
- citation-card-export-e2e + session-export-reimport switched from
placeholder/role-name lookups to the inline-capture testids so
they survive form-copy changes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
f42b4ec87c
commit
bef2725fdd
11 changed files with 309 additions and 148 deletions
|
|
@ -36,6 +36,10 @@ export function SessionMenu({ onExportZip, onImportZip, onOpenSamples }: Session
|
|||
const tick = useSessionListTick();
|
||||
const active = useActiveSession();
|
||||
const [debugTextLayer, setDebugTextLayer] = useDebugFlag("textLayer");
|
||||
const [hideCanvas, setHideCanvas] = useDebugFlag("hideCanvas");
|
||||
const [hideTextLayer, setHideTextLayer] = useDebugFlag("hideTextLayer");
|
||||
const [hideAnnotationLayer, setHideAnnotationLayer] = useDebugFlag("hideAnnotationLayer");
|
||||
const [hideXfaLayer, setHideXfaLayer] = useDebugFlag("hideXfaLayer");
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [newName, setNewName] = useState("");
|
||||
|
|
@ -407,25 +411,52 @@ export function SessionMenu({ onExportZip, onImportZip, onOpenSamples }: Session
|
|||
)}
|
||||
|
||||
<hr style={dividerStyle} />
|
||||
<label
|
||||
data-testid="session-menu-debug-textlayer"
|
||||
<div
|
||||
style={{
|
||||
...menuItemStyle,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 6,
|
||||
cursor: "pointer",
|
||||
padding: "4px 8px",
|
||||
color: "#666",
|
||||
fontSize: 11,
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: 0.5,
|
||||
}}
|
||||
title="Paint the PDF text-layer spans in yellow so you can see what's selectable. Also logs every selection event to the browser console."
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={debugTextLayer}
|
||||
onChange={(e) => setDebugTextLayer(e.target.checked)}
|
||||
style={{ margin: 0 }}
|
||||
/>
|
||||
Debug text layer
|
||||
</label>
|
||||
PDF diagnostics
|
||||
</div>
|
||||
<DebugCheckbox
|
||||
label="Highlight text layer"
|
||||
testid="session-menu-debug-textlayer"
|
||||
title="Paint the PDF text-layer spans in light grey so you can see what's selectable. Logs every selection event to the browser console."
|
||||
checked={debugTextLayer}
|
||||
onChange={setDebugTextLayer}
|
||||
/>
|
||||
<DebugCheckbox
|
||||
label="Hide canvas layer"
|
||||
testid="session-menu-hide-canvas"
|
||||
title="Hide the rendered glyphs so only the text/annotation overlay layers remain. Use to see if the textLayer covers regions where the canvas has no content."
|
||||
checked={hideCanvas}
|
||||
onChange={setHideCanvas}
|
||||
/>
|
||||
<DebugCheckbox
|
||||
label="Hide text layer"
|
||||
testid="session-menu-hide-textlayer"
|
||||
title="Hide the invisible selection text layer entirely. Use to see if it's covering the canvas content underneath."
|
||||
checked={hideTextLayer}
|
||||
onChange={setHideTextLayer}
|
||||
/>
|
||||
<DebugCheckbox
|
||||
label="Hide annotation layer"
|
||||
testid="session-menu-hide-annotation"
|
||||
title="Hide PDF annotations (stamps, form widgets, links). Use to see if a stamp is obscuring content or capturing your clicks."
|
||||
checked={hideAnnotationLayer}
|
||||
onChange={setHideAnnotationLayer}
|
||||
/>
|
||||
<DebugCheckbox
|
||||
label="Hide XFA layer"
|
||||
testid="session-menu-hide-xfa"
|
||||
title="Hide the XFA form layer (rare; only present on Adobe XFA forms)."
|
||||
checked={hideXfaLayer}
|
||||
onChange={setHideXfaLayer}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
|
|
@ -459,6 +490,38 @@ export function SessionMenu({ onExportZip, onImportZip, onOpenSamples }: Session
|
|||
);
|
||||
}
|
||||
|
||||
interface DebugCheckboxProps {
|
||||
readonly label: string;
|
||||
readonly testid: string;
|
||||
readonly title: string;
|
||||
readonly checked: boolean;
|
||||
onChange(next: boolean): void;
|
||||
}
|
||||
|
||||
function DebugCheckbox(p: DebugCheckboxProps) {
|
||||
return (
|
||||
<label
|
||||
data-testid={p.testid}
|
||||
title={p.title}
|
||||
style={{
|
||||
...menuItemStyle,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 6,
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={p.checked}
|
||||
onChange={(e) => p.onChange(e.target.checked)}
|
||||
style={{ margin: 0 }}
|
||||
/>
|
||||
{p.label}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
||||
const menuItemStyle: CSSProperties = {
|
||||
display: "block",
|
||||
width: "100%",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue