aboutsummaryrefslogtreecommitdiff
path: root/docs/specs
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-05 07:21:07 -0500
committerCraig Jennings <c@cjennings.net>2026-07-05 07:21:07 -0500
commit721185f10d1e389ae3816734b7b8174d33900314 (patch)
tree0e2a09a50e74e17200efc287e841d9e2bee8d8a3 /docs/specs
parent0af88d35a6f22c11e346970bec356bae0b74d4a2 (diff)
downloadarchsetup-721185f10d1e389ae3816734b7b8174d33900314.tar.gz
archsetup-721185f10d1e389ae3816734b7b8174d33900314.zip
docs(timer): record the shipped redesign and flip spec to IMPLEMENTEDHEADmain
The timer-panel UI/UX redesign built and shipped to dotfiles across five phased commits. This captures the archsetup-side records. The three design prototypes (the three-directions study, the hero-rack iteration, and the final) land under docs/prototypes, which the spec's Prototype iterations section links. The spec flips DOING to IMPLEMENTED with a history line summarizing the build. The manual-testing checklist is rebuilt around the redesigned panel (repeat timers, recurring alarms with snooze and a ringing state, the configurable pomodoro cycle, the stopwatch sweep dial, locked presets, and bar-tooltip parity), and the two obsolete fuzzel-dialog tests are marked superseded. A dated entry under the closed feature task records the redesign.
Diffstat (limited to 'docs/specs')
-rw-r--r--docs/specs/2026-07-02-timer-panel-spec.org170
1 files changed, 123 insertions, 47 deletions
diff --git a/docs/specs/2026-07-02-timer-panel-spec.org b/docs/specs/2026-07-02-timer-panel-spec.org
index ceb6e03..275bb2c 100644
--- a/docs/specs/2026-07-02-timer-panel-spec.org
+++ b/docs/specs/2026-07-02-timer-panel-spec.org
@@ -14,25 +14,32 @@
:PROPERTIES:
:ID: 1770af2e-b093-4024-a512-ae4324a2869f
:END:
-- [2026-07-05 Sun] IMPLEMENTED — built and shipped to dotfiles in a no-approvals speedrun (4 commits 1f4f270..78d3cbb): wtimer watch/lap/save; a new timer/ package with a GTK-free PanelModel (62 tests) + the GTK instrument-console panel; bar integration (custom/timer opens the panel, the fuzzel creation flow retired, Hyprland float rule added). Code-complete; live GTK behavior awaits Craig's manual pass (filed under "Manual testing and validation" in todo.org) — a failing check promotes to a bug.
+- [2026-07-05 Sun] IMPLEMENTED — redesign built and shipped to dotfiles in a no-approvals speedrun (5 commits =c7ac193=..=5a863b5=): the wtimer engine (timer repeat, recurring alarms with snooze/ringing/dismiss, =@half=/=@hour=/=+dur= alarm parse, the rebuilt configurable pomodoro cycle, bar-tooltip parity), the PanelModel view-data rebuild (=row_view=, ringing-first sort, per-type create options as flags, locked presets + half-past + named pomodoro cycles), the GTK hero-on-top panel (Cairo progress ring + stopwatch sweep dial, per-type create strips, one transport row, close ✕/Esc), and the bar tooltip parity. wtimer + timer suites 231 green, full =make test= green. Live GTK render is the manual checklist (todo.org). Stopwatch run-save deferred to vNext.
+- [2026-07-05 Sun] DOING — UI/UX redesign decided through a prototype process (research → brainstorm → several directions → iterate to final; see Prototype iterations below). The shipped v1 panel stands, but this rewrite supersedes its layout and adds functionality: a hero-on-top + rack layout, a live waybar-module preview at parity with =wtimer render=, per-type create-strip features (timer auto-repeat; alarm recurring weekdays + snooze + a ringing state; a configurable pomodoro cycle with work/rest short+long and a long-break interval; a stopwatch analog sweep dial + last-lap badge), presets (renamed from "chips") whose shipped defaults are locked and whose load flashes the fields, and a header close button. Stopwatch run-save is cut to a vNext. Rebuild pending — folds this decided design into the shipped =timer/= package.
+- [2026-07-05 Sun] IMPLEMENTED — v1 built and shipped to dotfiles in a no-approvals speedrun (4 commits 1f4f270..78d3cbb): wtimer watch/lap/save; a new timer/ package with a GTK-free PanelModel (62 tests) + the GTK instrument-console panel; bar integration (custom/timer opens the panel, the fuzzel creation flow retired, Hyprland float rule added). This is the base the 2026-07-05 redesign iterates on.
- [2026-07-05 Sun] DOING — Craig directed the build (no-approvals speedrun). Folded in the cj input from the sibling waybar-timer-module spec (GTK app styled like the panels; a queue/output-wall auto-sorted by fire time; stopwatch lap/stop + saveable runs; notify integration; 5/25-min configurable+deletable defaults; up to 10 timers; widget-gallery elements) — see Build scope below. Bypassed the READY spec-review step at Craig's direction; the four decisions were already resolved.
- [2026-07-04 Sat] DRAFT — all four decisions resolved by Craig (standalone; retire fuzzel once the panel lands; timer chips gain 10m/30m/2h; wtimer watch mode over polling). Decision-complete; ready for a spec-review to flip it READY before build.
- [2026-07-02 Thu] DRAFT — initial spec from Craig's roam capture "give the
timer a gtk UI/UX like the network panel. spec this out."
+** Prototype iterations
+The redesign ran through the UI/UX prototype process (see the =ui-prototyping= rule proposed to rulesets, 2026-07-05). Full working HTML prototypes over one shared engine, in the dupre instrument-console aesthetic; each iteration links here, newest last, so the design history is walkable.
+- [[file:../prototypes/2026-07-02-timer-panel-prototype-1.html][prototype-1]] — three initial directions over one shared engine: rack unit (faithful vertical list), transport deck (hero + track list), channel-strip board (vertical faders). Predates the formalized five-direction count.
+- [[file:../prototypes/2026-07-02-timer-panel-prototype-2.html][prototype-2]] — chose the rack direction; flipped to hero-on-top → create strip → list; made pomodoro a configurable cycle; locked the shipped presets (default cycle undeletable); dropped the stopwatch/pomodoro value entry.
+- [[file:../prototypes/2026-07-02-timer-panel-prototype-3.html][prototype-3]] — FINAL. Live waybar preview; hero donut moved right with one full-width button row; stopwatch sweep dial + ghost lap badge; alarm recurring days + snooze + ringing state; timer repeat; half-past alarm preset; presets flash on load; header close (Esc / bar-click reopen); verbatim tooltip labels; stopwatch save deferred.
+
* Metadata
-| Field | Value |
-|--------+---------------------------------------------------|
-| Status | implemented |
-|--------+---------------------------------------------------|
-| Owner | Craig Jennings |
-|--------+---------------------------------------------------|
-| Repo | dotfiles |
-|--------+---------------------------------------------------|
-| Kin | net panel (architecture donor), wtimer (backing), |
-| | desktop-settings panel spec (sibling) |
-|--------+---------------------------------------------------|
+| Field | Value |
+|--------+-----------------------------------------------------------------------------------------|
+| Status | implemented |
+|--------+-----------------------------------------------------------------------------------------|
+| Owner | Craig Jennings |
+|--------+-----------------------------------------------------------------------------------------|
+| Repo | dotfiles |
+|--------+-----------------------------------------------------------------------------------------|
+| Kin | net panel (architecture donor), wtimer (backing), desktop-settings panel spec (sibling) |
+|--------+-----------------------------------------------------------------------------------------|
* Problem
@@ -74,16 +81,41 @@ surface.
- Dupre WIP palette CSS shared with the net panel (same factoring the
desktop-settings spec calls for — one palette asset, three panels).
-** Layout sketch
-
-- Header row: running-item count + a Clear All button (maps to cancel-all).
-- Item list: one row per item — type glyph, label, live countdown / clock
- time / phase+cycle for pomodoro, pause and cancel buttons, click-to-promote.
-- Create strip: four type buttons (the wtimer glyphs), preset chips per type
- (timer 5m / 10m / 15m / 25m / 30m / 60m / 2h; alarm +30m / top-of-hour /
- 07:00; pomodoro default cycle; stopwatch none — decision C), a freeform
- entry validated with wtimer's own parsers, an optional label field.
-- Empty state: the create strip alone, centered.
+** Layout sketch (decided in prototype-3)
+
+Top-to-bottom, one column:
+
+- Header: brand + live item count + Clear All + a flat circular close ✕
+ (tooltip "Close (Esc)"), matching the net/bt/audio panels. Esc closes;
+ clicking the bar's timer module reopens it (mirrors =on-click: timer-panel=).
+- Hero (the primary / bar-slot item): the info block (type badge, any feature
+ badges, pomodoro cycle dots, label, big countdown, subline) on the left with
+ the progress donut on the right, and all its controls in one full-width,
+ left-justified button row beneath. Countdown types show a filling progress
+ ring; a stopwatch shows an analog sweep dial (a gold second-hand, one
+ revolution per minute) with its last lap as a bordered ghost badge beside the
+ count — no fake progress ring for a count-up. The ‹ › keys cycle the primary
+ through the whole queue, wrapping at either end.
+- Create strip: the four type buttons, then a per-type body — presets (renamed
+ from "chips") + a freeform entry validated by wtimer's parsers + an optional
+ label, plus per-type extras (see Build scope). Loading a preset flashes the
+ target fields rather than toasting. Shipped presets are locked (no delete);
+ only presets you add carry a ×.
+- Queue list: the rest of the items (everything but the hero), soonest-fire
+ first, one rack row each — lamp, glyph, label, subline, countdown, and inline
+ pause / promote / cancel (two-stage arm). Stopwatches are promotable to the
+ hero like any other item. With a single item the list reads "Only one item is
+ queued. Add more above." Empty state: hero shows "No timers running", create
+ strip below.
+
+** Waybar module parity
+
+A live preview above the panel renders exactly what =wtimer render= emits for
+the bar: =<large glyph> <countdown>= plus =+N= for the other items, recoloured
+by state (urgent < 60 s terracotta, paused dim, pomodoro-work gold,
+pomodoro-break sage, idle silver), with the full per-item hover tooltip. Tooltip
+lines show each item's label verbatim — no phase word appended. The panel and
+the bar stay one source of truth via the wtimer watch subscription.
** What happens to the fuzzel flow
@@ -93,25 +125,26 @@ click-driven bar path and the keybind/fuzzel path. Until the panel ships the
fuzzel flow stays (it's styled and tested); phase 4 removes it after the
panel proves out.
-* Build scope (consolidated 2026-07-05 — the four decisions plus Craig's cj input)
+* Build scope (decided design — folds the prototype-3 redesign into the shipped =timer/= package)
-The panel is a new =timer/= dotfiles package mirroring =net/= and =audio/= (src-layout, GTK4 + gtk4-layer-shell, humble-object PanelModel, instrument-console faceplate aesthetic — machined plate, engraved section labels, status lamps, console keys). wtimer stays the state engine; the panel is a view over it.
+The panel is the existing =timer/= dotfiles package (src-layout, GTK4 + gtk4-layer-shell, humble-object PanelModel, instrument-console faceplate). wtimer stays the state engine; the panel is a view over it. This rebuild reshapes the layout (see Layout sketch) and adds the per-type functionality below. UI idioms draw from the widget gallery (=docs/prototypes/2026-07-03-panel-widget-gallery-prototype.html=); the reference build is prototype-3.
-Create + queue:
-- A configure strip (top): pick timer / alarm / stopwatch / pomodoro, set the value (preset chips per decision C + a freeform entry validated by wtimer's parsers, optional label). A =+= adds the configured item to the queue.
-- The queue is an output-wall-style list (the instrument-console output well), *auto-sorted by soonest fire time* (the item that notifies next is on top). One row per item: type glyph, label, live countdown / clock time / pomodoro phase+cycle, pause/resume, cancel, click-to-promote (bar glyph slot).
-- Up to 10 timers; the two starting timer presets default to 5 min and 25 min, and the preset set is configurable and deletable.
+Queue + primary:
+- Up to 10 items, auto-sorted by soonest fire time (four buckets: active countdown < paused countdown < active stopwatch < paused stopwatch). The soonest-firing is the hero/primary (the bar glyph slot). Promote via a row's promote key or by cycling ‹ ›; cycling and promotion include stopwatches and wrap around the whole list.
+- The hero shows the primary big; the list shows the rest. Clear All cancels everything.
-Stopwatch:
-- A running stopwatch row has a Lap button and a Stop button. Lap records the elapsed time at the press; unlimited laps; a lap can optionally be named (non-interruptive — naming never blocks further laps). On stop, the full run (splits + optional names) can be saved to review later. Save target: an org file (default =~/org/stopwatch-runs.org=, override via a config key) — one heading per run with a table of laps.
+Types + create strip:
+- *Timer*: preset durations 5m / 25m / 10m / 15m / 30m / 60m / 2h (5m and 25m first), freeform entry (wtimer parser), optional label, and a *repeat* toggle — a repeating timer re-arms itself on fire instead of clearing.
+- *Alarm*: presets +30m / top-of-hour / *half-past* (next X:30) / 07:00, freeform HH:MM, optional label, a *recurring weekday* selector (S M T W T F S, with weekdays / daily shortcuts) and a *snooze* duration. An alarm fires into a *ringing* state rather than silently vanishing: the hero/row shows SNOOZE (re-arm by the snooze minutes) and DISMISS (a recurring alarm re-arms to its next matching day; a one-shot clears).
+- *Stopwatch*: no value entry — counts up from zero. Lap (unlimited) and Stop. The hero shows an analog sweep dial and the last lap as a ghost badge beside the count. *Run-save is deferred to a vNext* (cut from v1's org-save plan — see the status history).
+- *Pomodoro*: a configurable cycle — Work and Rest each with a short and a long duration, a "long break every N cycles" interval, and an auto-advance toggle. Every Nth ("deep") cycle uses the long work + long rest together. Cycle progress shows as dots in the hero and row. With auto-advance off, each phase end waits for a Start press. Preset cycles (Classic 25/5/15, Deep 50/10/30, Sprint 15/3/10) load the fields.
+- *Presets*: shipped defaults are locked (undeletable — the pomodoro default cycle can't be removed); presets you add carry a × and are deletable. Loading any preset flashes the target fields (no toast).
Live updates + notifications:
-- A new =wtimer watch= subcommand emits state on every change (state-file watch → JSON lines on stdout); the panel subscribes for push updates instead of polling. The bar may adopt it later.
-- Notifications for alarms and timers go through the =notify= script (wtimer already fires notify on completion; keep that path the single notification owner).
-
-UI elements: draw from the panel widget gallery prototype (=docs/prototypes/2026-07-03-panel-widget-gallery-prototype.html= in the archsetup repo) for the console keys, lamps, output-well rows, and chips, matching the shipped net/bt/audio look.
+- A =wtimer watch= subcommand emits state on every change (state-file watch → JSON lines on stdout); the panel subscribes for push updates instead of polling (decision D). Notifications for alarms and timers go through the =notify= script — wtimer stays the single notification owner.
-Retire the old timer: the bar's =custom/timer= on-click drives =wtimer new= (the fuzzel chain). Rewire the bar module's on-click to open this panel, and retire the =wtimer new= fuzzel creation flow (decision B). Keep =wtimer render= as the bar indicator and the wtimer engine as the state source.
+Bar + window:
+- =custom/timer= left-click opens the panel; =wtimer render= stays the bar indicator (glyph + countdown + =+N=, state-coloured, verbatim tooltip labels). A header close ✕ and Esc close the panel; clicking the bar module reopens it. The =wtimer new= fuzzel creation flow is retired (decision B).
* Decisions (Craig)
@@ -131,15 +164,58 @@ Resolved (Craig, 2026-07-04): timer chips are 5m / 10m / 15m / 25m / 30m / 60m /
CLOSED: [2026-07-04 Sat]
Resolved (Craig, 2026-07-04): a wtimer watch/subscribe mode, not 1s polling. This grows wtimer with a new watch capability that the panel (and potentially the bar) subscribes to for live state, rather than reusing the poll cadence — cleaner at the cost of a wtimer addition. Fold the watch mode into the phase 1 CLI-backing seam.
-* Implementation phases
-
-1. PanelModel presenter + CLI-backing seam (TDD, GTK-free, 100% like the net
- PanelModel), plus the wtimer watch/subscribe mode (decision D) the presenter
- subscribes to for live state.
-2. Blueprint UI: item list + create strip, wired to the presenter; palette
- css factored to the shared asset.
-3. Bar integration: timer module left-click opens the panel (replacing the
- fuzzel menu binding there); the panel and bar both track state via the
- wtimer watch subscription.
-4. AT-SPI smoke + manual-testing checklist; retire the fuzzel flow (decision B)
- after the panel proves out over a week of real use.
+The decisions below were resolved live through the prototype iteration (2026-07-05), each seen working in a prototype before being written down.
+
+** DONE Layout: hero on top, then create strip, then the queue list
+CLOSED: [2026-07-05 Sun]
+Resolved: the primary item rides a hero at the top (info left, donut right, all controls in one full-width button row), the create strip sits under it, the rest of the queue below. Chosen over the transport-deck and channel-strip directions in prototype-1.
+
+** DONE Stopwatch hero visual: analog sweep dial, not a progress ring
+CLOSED: [2026-07-05 Sun]
+Resolved: a count-up stopwatch shows a gold second-hand sweeping once per minute, with its last lap as a bordered ghost badge beside the count — not a fake progress ring (a stopwatch has no target to be a fraction of).
+
+** DONE Alarm: recurring weekdays + snooze + a ringing state; add a half-past preset
+CLOSED: [2026-07-05 Sun]
+Resolved: alarms carry a weekday-repeat selector and a snooze duration, and fire into a ringing state with SNOOZE / DISMISS rather than vanishing. A half-past preset joins top-of-hour (fires at the next X:30). Drawn from Alarm Clock Xtreme / Alarmy.
+
+** DONE Timer: auto-repeat toggle
+CLOSED: [2026-07-05 Sun]
+Resolved: a timer can repeat — it re-arms itself on fire instead of clearing. Drawn from MultiTimer / Multi Timer.
+
+** DONE Pomodoro: a fully configurable cycle
+CLOSED: [2026-07-05 Sun]
+Resolved: Work and Rest each get a short and a long duration, plus a long-break-every-N interval and an auto-advance toggle; every Nth deep cycle uses the long work + long rest; progress shows as cycle dots. The default cycle preset is locked (undeletable). Drawn from Pomofocus / the classic technique.
+
+** DONE Presets (formerly "chips"): lock defaults, flash on load
+CLOSED: [2026-07-05 Sun]
+Resolved: rename "chips" to "presets"; shipped defaults are locked (no delete), presets you add are deletable; loading a preset flashes the target fields instead of firing a toast.
+
+** DONE Stopwatch run-save: deferred to a vNext
+CLOSED: [2026-07-05 Sun]
+Resolved: v1's "save the run's splits to an org file on stop" is cut from this build. Stop just stops. Revisit in a vNext if the need is real.
+
+* Implementation phases (redesign rebuild)
+
+Folding prototype-3 into the shipped =timer/= package. TDD throughout — GTK-free
+logic first, GUI last — reviewing between phases. Each phase is a dotfiles commit
+under the archsetup-owns-dotfiles rule.
+
+1. wtimer engine: alarm recurring-days + snooze + a ringing state, timer repeat,
+ the configurable pomodoro cycle (work/rest short+long, long-break interval,
+ auto-advance, deep cycle), half-past parsing, and the watch/subscribe mode
+ (decision D). Extend wtimer's own suite per addition.
+2. PanelModel: the four-bucket soonest-fire sort, promote/cycle wrap (stopwatches
+ included), per-type create validation + presets (locked defaults, custom
+ delete, flash-on-load), and the row/hero view data (sweep fraction, cycle
+ dots, last lap, feature badges, ringing controls). GTK-free, unit-tested like
+ the net PanelModel.
+3. GTK GUI: the hero (progress ring / sweep dial, one full-width button row, lap
+ badge), the per-type create strip (timer repeat toggle; alarm weekday selector
+ + snooze; pomodoro config grid; presets that flash), the header close ✕,
+ Esc-to-close, and bar-click reopen.
+4. Bar parity: =wtimer render= tooltip labels verbatim, state classes confirmed;
+ panel and bar track one state via the watch subscription.
+5. AT-SPI smoke + a manual-testing checklist (todo.org). Retire the =wtimer new=
+ fuzzel flow (decision B) after the panel proves out.
+
+Deferred to a vNext: stopwatch run-save (an org log of splits).