Files
brain-of-reese/.agent/user_stories/document-modal.md
T

55 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Story: Open Documents in a Modal (Almost-Fullscreen)
**Phase:** `26_document_modal_viewer.md` · **E2E:** `tests/e2e/test_document_viewer.py`
## Narrative
As **a user**, when I click a document source chip (in the chat) or a
document path link (in the Sources table), I want the document to open
**right where I am** — in an almost-fullscreen modal overlay — instead of
navigating away to a new page/tab. I want to read it, then close the modal
and keep going.
- **Given** a document cited in a chat answer (or listed in Sources)
- **When** I click its chip / path link
- **Then** the document opens in an almost-fullscreen modal on the same
page, rendered exactly as the `/document.html` viewer renders it
(markdown in a centered column, other formats in a mono `pre`), with a
close button, Escape-to-close, and backdrop-to-close; and the dedicated
`/document.html` page still works for direct links / no-JS fallback.
## Acceptance criteria
1. Clicking a source chip or a Sources-table path link opens the document
in a modal (`#doc-modal`, `.doc-modal-panel`, ~`96vw × 92vh`) on the
current page — **no new tab, no navigation**.
2. The modal renders the same content as `/document.html`: md/markdown via
the shared escape-first renderer (`.doc-md`), other formats in
`<pre class="doc-raw">`, source/format/path/indexed/chunks meta.
3. The modal closes on the close button, on `Escape`, and on backdrop
click; focus moves into the panel on open and returns on close.
4. The modal honours the dark theme, `prefers-reduced-motion`, no-CDN, and
the ≥4.5:1 contrast / focus-visible a11y rules.
5. The standalone `/document.html` page is unchanged (direct link, back
button, not-found state, XSS-safe rendering).
6. No new packages; vanilla HTML/CSS/JS; the modal reuses the existing
stateless `GET /api/documents/content` endpoint (no backend change).
7. Story E2E green in isolation, no regressions in the document-navigation
/ header / smoke suites, one `--no-gpg-sign` commit.
## Playwright Mapping Rule
**Test Scenario → `tests/e2e/test_document_viewer.py`** (mock LLM, seeded
KB — same harness as the phase-10 suite):
1. `test_source_chip_opens_modal` — chip → modal opens in-page (no popup),
title + `.doc-md` content present, page URL unchanged.
2. `test_sources_row_opens_modal` — Sources path link → modal, yaml in
`<pre.doc-raw>`, mono font.
3. `test_modal_closes_on_button_escape_and_backdrop` — close via button,
backdrop, and `Escape`.
4. `test_modal_focus_and_a11y` — `role="dialog"` + `aria-modal`, focus
inside the panel, close button has an `aria-label`.
5. `test_modal_xss_safe` — hostile md renders escaped, no dialog fires.
6. `test_standalone_page_still_works` — `/document.html` still renders,
not-found, dark theme, no-CDN, a11y frame, ≤736px md column.
7. `test_modal_theme_and_no_cdn` — dark surface; all assets same-origin /
`data:`.