From b3aea00cbbb29ab60a579e6ef47160d6431e1eac Mon Sep 17 00:00:00 2001 From: Lucas Winther Date: Tue, 18 Aug 2026 03:59:52 +0200 Subject: [PATCH] feat(ui): call the list view Checklist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Ending soon" described the sort, not the job — and it sat one line above a sort control whose own option reads "Ending soonest", so the tab and the ordering looked like the same control said twice. Checklist is what a reader with four games is doing with it. The stored id stays "soon". That value is in `prefs.view` on real devices, and a label is copy: renaming one must never move a reader to the other view. Co-Authored-By: Claude Opus 5 (1M context) --- docs/PRD.md | 6 +++++- src/client/App.tsx | 5 ++++- src/client/components/Welcome.tsx | 2 +- test/views.test.tsx | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/PRD.md b/docs/PRD.md index 6aff88c..e1fa6bb 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -86,11 +86,15 @@ back through and that pushed every other bar off to the right. An event older th its faded left edge rather than being redrawn as though it started at the edge — the same honesty the frayed right edge carries for an unannounced end. -**F2 — Ends-soonest list.** +**F2 — Checklist (the ends-soonest list).** A flat list of all *currently running* events sorted ascending by end date, with a relative countdown ("ends in 2 days", "ends in 4 hours"). Under 24 hours, the row is emphasized. This is the view that justifies the app, and it is one tap from the timeline. +The tab reads **Checklist**, which is what a reader with four games is doing with it: working down a +list of jobs with deadlines. Its stored id stays `"soon"` — that value is in `prefs.view` on real +devices, and renaming a label must never move a reader to the other view. + **Which view opens is the reader's answer, not ours.** This spec said "calendar (default)" and the app shipped opening on the list; both were a decision made on the reader's behalf and then forgotten on every reload. So the first run asks (F8) and the answer is stored in `prefs.view`. The list is diff --git a/src/client/App.tsx b/src/client/App.tsx index 0268ccd..f9b9ae3 100644 --- a/src/client/App.tsx +++ b/src/client/App.tsx @@ -356,9 +356,12 @@ export function App() { aria-label="View" className="flex rounded-lg border border-hairline p-0.5" > + {/* The id is a stored value (`prefs.view`) and the label is copy, so + they are allowed to drift: renaming the tab must not silently move + every reader to the other view. */} {( [ - ["soon", "Ending soon"], + ["soon", "Checklist"], ["timeline", "Timeline"], ] as const ).map(([id, label]) => ( diff --git a/src/client/components/Welcome.tsx b/src/client/components/Welcome.tsx index 38f12cf..b20babf 100644 --- a/src/client/components/Welcome.tsx +++ b/src/client/components/Welcome.tsx @@ -165,7 +165,7 @@ function ViewChoice({ hues: string[]; }) { const options: Array<{ id: View; label: string; hint: string }> = [ - { id: "soon", label: "Ending soon", hint: "A list, closest deadline first." }, + { id: "soon", label: "Checklist", hint: "A list, closest deadline first." }, { id: "timeline", label: "Timeline", hint: "Bars per game, today pinned." }, ]; diff --git a/test/views.test.tsx b/test/views.test.tsx index 31116b6..0214aba 100644 --- a/test/views.test.tsx +++ b/test/views.test.tsx @@ -104,7 +104,7 @@ describe("Welcome (first run)", () => { test("asks how the reader wants to see their events", () => { expect(html()).toContain("How do you want to see them?"); - expect(html()).toContain("Ending soon"); + expect(html()).toContain("Checklist"); expect(html()).toContain("Timeline"); });