Each row in the document search list and the enrichment queue gets a
WCAG-compliant (44px touch target) checkbox bound to bulkSelectionStore.
Checkbox click does not trigger the row's stretched-link navigation —
it sits inside the z-10 content sibling, the link is in the z-0 sibling,
so click events do not bubble between them.
Refs #225
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Nesting the tag <button> inside the row's <a href="…"> made the browser
treat any click on the button as a click on the anchor, sending the
user to the document detail page even though the tag handler called
goto() with the tag-filter URL. e.stopPropagation() doesn't cancel
the anchor's default navigation.
Refactor to the stretched-link pattern: the row-wide anchor sits as an
overlay (`absolute inset-0 z-0`) and the content wrapper sits above it
(`relative z-10` + `pointer-events-none`). Tag buttons re-enable
pointer events with `pointer-events-auto`, so they're true siblings of
the anchor and receive their own clicks. Empty content areas pass
through to the anchor for whole-row navigation.
The vitest-browser client project doesn't load Tailwind CSS, so the
z-index has no effect there and Playwright's coordinate-based click
hits the anchor instead of the button. Trigger the click directly on
the button DOM element in the unit test (with a comment explaining the
test-env constraint); the actual user-facing behavior is verified via
playwright against the running dev server.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Refill the columns that went visually empty after the previous dedup
commit (`fc0fc57`):
- Middle column gains the document `summary` (line-clamp-2, italic,
with `summaryOffsets` highlighting — the backend already populates
the offsets, the frontend just wasn't rendering them) and a row of
thin neutral chips for `archiveBox`, `archiveFolder`, and `location`
(~99% of docs in the corpus carry these). Chips are desktop-only
and skip empty values.
- Right column restores `VON sender` and `AN receivers`, now with
`<mark>` highlighting that the previous right-column copy lacked,
so search matches stay visible there.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The desktop document-list row showed sender/receiver twice — once
side-by-side in the middle column and again stacked in the right
column. Stack the middle-column block vertically (the side-by-side
grid wasted horizontal space and competed with the larger thumbnail)
and remove the now-redundant copy from the right column.
The middle-column block keeps the search-match highlighting, which the
right-column copy never had.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- ContributorStack: text-xs for WCAG 1.4.4 (was text-[10px]), safeColor()
validation to block CSS injection via actor.color, role="img" aria-label
on empty placeholder, {#each} keyed by index
- ContributorStack spec: update empty-state assertion to getByRole('img')
- DocumentRow spec: add stopPropagation regression test for tag click
- documents/page.svelte.spec.ts: new — debounce, URL building, initial state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>