feat(timeline): make it a board, with the axis and the names pinned
The reader who was asked what good looks like named paimon.moe's timeline, and the thing ours was missing is what that view never loses: on a wide window we drew more calendar and nothing that said which day, whose game, or which event was on screen. The date axis, the lane names and the event names all scrolled away together — and a six-week bar starts weeks off the left edge, so its name went with its start date and left a coloured rectangle. So it is a pane that scrolls in both directions, with the axis stuck to the top and every name stuck to the left. A name is sticky inside its own bar, so it can never wander onto an event it does not belong to. The axis gained the week the schedules are actually written in: a dated tick every Monday and a brighter rule at each month. The frozen label column that started this went away again — it stood on the calendar and ate the names it was meant to keep. Lane names sit on their own line instead, and "jump to today" sits in the board's header rather than floating over the dates it sends you back to. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1cd9579280
commit
e489697540
+13
-6
@@ -63,7 +63,7 @@ no stored key. A game may have several sources; see `docs/INGESTION.md` § Three
|
||||
|
||||
### Features
|
||||
|
||||
**F1 — Calendar view (default).**
|
||||
**F1 — Timeline view.**
|
||||
A horizontal timeline, one lane per game, spanning a scrollable date range with "today" pinned as a
|
||||
vertical marker. Each event is a bar from `startsAt` to `endsAt`. Bars are colored by game, and
|
||||
completed events render at reduced opacity with a check. Clicking a bar opens a detail panel with
|
||||
@@ -72,22 +72,29 @@ title, type, exact start/end in the user's local timezone, source link, and a co
|
||||
An event with `endsAt: null` renders as a bar with a frayed right edge and the label "end date
|
||||
unknown" — it must be visually distinct from an event that ends far in the future.
|
||||
|
||||
It is a board rather than a stretch of page: its own pane, scrolling in both directions, with the
|
||||
date axis pinned to the top and every name — the lane's and the event's — pinned to the left edge.
|
||||
Those three used to scroll away together, which made a wide window worse rather than better: more
|
||||
calendar on screen, and nothing left saying which day, whose game, or which event was being read. A
|
||||
six-week bar starts weeks off-screen, so a name that rides off with its own start date leaves a
|
||||
coloured rectangle behind.
|
||||
|
||||
**F2 — 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 list is capped and offers the rest.** Two games already run to twenty-one live events, and a
|
||||
reader who tried exactly that said the list stopped being usable. Each section shows a handful with
|
||||
an explicit "show all N". This truncates the *view* only: the order is untouched, and the rows below
|
||||
the cut are still counted in the header, still on the timeline, and one tap away.
|
||||
|
||||
**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
|
||||
what the question ships pre-answered with — a reader cannot choose between two layouts they have not
|
||||
seen, and it is the view that answers "what expires next" in one look.
|
||||
|
||||
**The list is capped and offers the rest.** Two games already run to twenty-one live events, and a
|
||||
reader who tried exactly that said the list stopped being usable. Each section shows a handful with
|
||||
an explicit "show all N". This truncates the *view* only: the order is untouched, and the rows below
|
||||
the cut are still counted in the header, still on the timeline, and one tap away.
|
||||
|
||||
**F3 — Mark completed.**
|
||||
A toggle on every event, in both views. State is written to `localStorage` immediately and
|
||||
optimistically — there is no server round trip and no failure case. Completed events stay visible
|
||||
|
||||
Reference in New Issue
Block a user