timer band
Timer Band
Section titled “Timer Band”A band beneath the topbar that shows elapsed time against a goal (e.g. “2-minute swap”), with warn and over-goal states. Persistent across screens within a flow — its job is to give the operator continuous awareness that the clock is running.
The progress indicator is a circular ring, not a linear bar. Linear progress would visually compete with the [[step-stepper|step-dots stepper]] in the same vertical region; the ring is unmistakably the timer.
When to use
Section titled “When to use”- A flow has a service-level target (battery swap goal: 2 minutes; QA inspection goal: 5 minutes)
- The operator’s job is to hit the target consistently
- Awareness of remaining time should be passive — visible but not intrusive
Not for: countdown timers users explicitly wait for (use a [[status-card]] with elapsed text), one-off processes (use inline copy).
Anatomy
Section titled “Anatomy” ╭───╮ Swap time( 1:23 ) of 2:00 goal ╰───╯- Container
.timer-band:padding: 4px 20px 12px,display: flex,align-items: center,gap: 12px,flex-shrink: 0. - Ring
.timer-ring: 44×44px wrapper. SVGviewBox="0 0 40 40", two centered<circle>s at (20,20),r=18, stroke-width 4. Track strokevar(--grey4). Fill strokevar(--g-primary),stroke-linecap: round,stroke-dasharray: 113.097(= 2π·18),stroke-dashoffsetinterpolated from full circumference (empty) to 0 (full ring). SVG rotated-90degso the arc starts at 12 o’clock and grows clockwise. - Ring value: absolutely positioned text inside the ring, 11px / 700 tabular-nums,
letter-spacing: -0.02emso1:23fits comfortably. Reads elapsed (1:23) while under, over-goal form (+0:43) once exceeded. - Meta: stacked label + goal beside the ring. Label
Swap timeat 12px / 600. Goalof 2:00 goalat 11px / 500 grey, flips toover goalonce exceeded.
State machine
Section titled “State machine”| State | Condition | Ring fill | Value + goal text |
|---|---|---|---|
good |
elapsed < (goal − 30s) | --g-primary |
--g-dark |
warn |
(goal − 30s) ≤ elapsed < goal | --amber10 |
--amber11 |
over |
elapsed ≥ goal | --red9 |
--red9 |
Apply the state class to the .timer-band root; ring fill, value, and goal text recolor via descendant selectors.
Behavior
Section titled “Behavior”- Single
setInterval(tick, 1000)for the active swap. Don’t spin up per-screen intervals. - Hide on dashboard, support log, and success/complete screens — anywhere the swap isn’t actively in motion.
- Inject via a
DOMContentLoadedhook that finds every.topbarand prepends a.timer-band(skip topbars on excluded screens). This keeps the markup DRY across many screens. - Display in elapsed form (
1:23) while under goal, then flip to over-goal form (+0:43) once exceeded.
Forbidden
Section titled “Forbidden”- Audio or haptic on cross-threshold — the visual color shift is sufficient, alarms would be invasive in a high-touch retail context.
- Resetting on screen change — the timer follows the swap, not the screen.
- Pause control — operators don’t pause the timer; if they need to stash work, they [[parked-queue|park the swap]] entirely.
Reference implementation
Section titled “Reference implementation”See .timer-band / .timer-ring* CSS, tickTimers(), and updateTimerVisibility() in products/rechaj-swap-app/prototypes/support-cases-v3.html.