docs(adr): ADR-031 inline-expand summary + Q&A in the list (issue #16)
This commit is contained in:
@@ -1219,6 +1219,54 @@ stops scraping; the app is unaffected. No schema change.
|
||||
|
||||
---
|
||||
|
||||
## ADR-031 — SPA-like reader: inline-expand summary + Q&A in the list (HTMX, no framework)
|
||||
|
||||
**Status:** Proposed (2026-06-12). Issue #16. **Draft for review — no code yet.**
|
||||
|
||||
**Context / requirements.** The reader is multi-page: a list of compact cards (`/`), then a
|
||||
navigation to a separate detail page (`/v/{id}`) for the full summary + the docked chat (ADR-027).
|
||||
It feels less fluid than a single integrated view. We want the full summary AND the per-video
|
||||
Q&A to open **in place in the list**, no page hop. Requirements:
|
||||
- R1: clicking a summarized card expands it in place to the full summary (summary/highlights/
|
||||
takeaways) + the chat dock; a collapse returns it to the compact card.
|
||||
- R2: **no SPA framework** — stay HTMX + Templ (ADR-003); reuse existing fragments, not a rewrite.
|
||||
- R3: **progressive enhancement** — with JS off, the card link still navigates to `/v/{id}`
|
||||
(the detail page stays as the no-JS + deep-link surface). Nothing becomes JS-only.
|
||||
- R4: only **summarized** cards expand; pending/rate-limited/no-caption cards keep their current
|
||||
footer behaviour (Summarize button, waiting/none states).
|
||||
- R5: chat inside an expanded card works exactly as on the detail page (reuse `chatReveal`/
|
||||
`chatSection` + the existing `/v/{id}/chat` endpoints, unchanged).
|
||||
|
||||
**Decision / architecture.**
|
||||
1. **Reuse the existing fragments.** `summaryBody(r)` and `chatReveal(videoID)` already exist and
|
||||
render the detail page; a new `expandedCard(r, chatEnabled)` composes the compact header + a
|
||||
collapse control + `summaryBody` + `chatReveal`. `DetailPage` is refactored to also compose
|
||||
`summaryBody` so the two never drift (DRY).
|
||||
2. **Two fragment endpoints** (mirroring the existing list/status HTMX fragment pattern):
|
||||
`GET /v/{videoId}/expand` → `expandedCard`; collapse reuses the existing compact `VideoCard`
|
||||
via `GET /v/{videoId}/card`. Both are list-card `<li>` fragments with the SAME `id`
|
||||
(`video-{id}`), swapped `outerHTML` — same mechanism as `processingCard`/`VideoCard` today.
|
||||
3. **The compact card's title/"Read" affordance** becomes `hx-get=/v/{id}/expand`,
|
||||
`hx-target=#video-{id}`, `hx-swap=outerHTML`, with `href=/v/{id}` as the no-JS fallback (R3).
|
||||
The expanded card's collapse control is the inverse (`hx-get=/v/{id}/card`).
|
||||
4. **Only when `r.Summarized`** does the expand affordance render (R4); the other states are
|
||||
unchanged.
|
||||
5. **v1 does NOT push the URL** (`hx-push-url`) — expand/collapse is ephemeral list UI state; the
|
||||
detail page remains the deep-link/shareable URL. Deep-linking the open state via `hx-push-url`
|
||||
is noted as a later option (needs list-state restore on back).
|
||||
|
||||
**Out of scope / later.** URL push / deep-linkable open state; the visual refresh (#17) — though
|
||||
the expanded-card markup is where #17's TUI/charm styling will land, so they pair.
|
||||
|
||||
**Reversibility.** Additive: two fragment endpoints + one templ + an affordance swap on the
|
||||
compact card. Removing the affordance reverts to plain list→detail navigation; the detail page is
|
||||
untouched. No schema change.
|
||||
|
||||
**Next steps (gated):** on approval → BDD (`docs/use-cases/inline_expand.feature` + coverage
|
||||
map) → TDD → implement → SemVer + docs.
|
||||
|
||||
---
|
||||
|
||||
## Rejected alternatives
|
||||
|
||||
Approaches considered during the 2026-06-02 planning + grill session and **deliberately not
|
||||
|
||||
Reference in New Issue
Block a user