diff --git a/docs/specs/video-card-states.md b/docs/specs/video-card-states.md new file mode 100644 index 0000000..d26c587 --- /dev/null +++ b/docs/specs/video-card-states.md @@ -0,0 +1,70 @@ +# Spec — Unify video-card states: one "Summarize now" verb, honest no-captions state + +**Repo:** tapir · **Size:** small, **view-layer only** (`views.templ` + a little CSS in +`view.go`; regenerate `views_templ.go`). No handler, store, or DB change. The two existing +handlers (`/summarize`, `/retry-now`) stay exactly as they are — only what the card *shows* +changes. + +**Why.** The video card today presents two different verbs — "Try now" (`.btn-retry`, on +rate-limited videos) and "Summarize" (`.btn-secondary`, on pending videos) — for what the user +experiences as one intent: *"summarize this video now."* The user doesn't know or care about the +internal pipeline state (rate-limited vs. manual-queue); two differently-labelled, differently- +styled buttons leak that state machine into the UI as a choice. Also: a **no-captions video +(`TranscriptStatus == "none"`) currently falls into the `else` branch and wrongly shows a +"Summarize" button** that, if clicked, tries and fails — there are no captions to fetch. That's +the confusing dead-end to remove. + +In normal use the maintainer is in **auto mode**, so these buttons are *exceptions*, not the main +path — videos summarize themselves. So the card should be **status-first**: the state is what the +user reads constantly; the manual nudge is a small, quiet affordance for impatience, not a +prominent call-to-action. + +## The honest per-state card model (footer of `VideoCard`) + +Restructure the footer branch in `VideoCard` (in `internal/web/views.templ`) to these states. +The branch ORDER matters (summarized first, then terminal/no-action states, then actionable): + +1. **Summarized** — preview + provider chip + fallback badge + actions. **No button.** (unchanged) +2. **No captions** (`r.TranscriptStatus == "none"`) — **NEW branch.** Quiet status text, e.g. + `No transcript available` (use a muted `.card-state`/`.chip-retry`-style treatment, NOT a + button). This is a terminal honest dead-end — the user can do nothing, so offer nothing. +3. **Queued / requested** (`r.SummarizeRequested`) — "Queued · waiting for the next run". **No + button.** (unchanged) +4. **Rate-limited** (`r.TranscriptStatus == "rate_limited"`) — quiet status (keep the + "fetching soon" sense) + a **quiet "Summarize now"** button POSTing to `retryNowURL` (clears + backoff then processes). Same quiet style as state 5. +5. **Pending** (else — discovered, not yet attempted) — quiet "Not summarized" + a **quiet + "Summarize now"** button POSTing to `summarizeURL` (flips the queue flag then processes). + +## Unify the verb and the style +- **One label everywhere a manual nudge is offered: "Summarize now"** (states 4 and 5). Drop the + "Try now" wording entirely. +- **One quiet style** for both: use the understated `.btn-retry` pattern (small, pill, outline, + transparent bg) — NOT `.btn-secondary`/`.btn` (heavier). Rename the CSS class to something + state-neutral (e.g. `.btn-quiet` or `.btn-summarize-now`) so it no longer reads as + "retry"-specific; keep the same visual. The point: the nudge is subtle, status is primary. +- Keep both `