diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-05 07:21:07 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-05 07:21:07 -0500 |
| commit | 721185f10d1e389ae3816734b7b8174d33900314 (patch) | |
| tree | 0e2a09a50e74e17200efc287e841d9e2bee8d8a3 /docs/specs/2026-07-02-timer-panel-spec.org | |
| parent | 0af88d35a6f22c11e346970bec356bae0b74d4a2 (diff) | |
| download | archsetup-721185f10d1e389ae3816734b7b8174d33900314.tar.gz archsetup-721185f10d1e389ae3816734b7b8174d33900314.zip | |
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/2026-07-02-timer-panel-spec.org')
| -rw-r--r-- | docs/specs/2026-07-02-timer-panel-spec.org | 170 |
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). |
