Show a timer in the day bar while a walk is on

The bar already carries the asleep/awake counter; a walk in progress had
nothing, so "how long have we been out" meant going to the Walks panel to look.
It gets a second pill now, counting from the walk's start, and tapping it ends
the walk — the same bargain the sleep pill offers for the sleep boundary.

Two timers no longer fit beside the day controls on a narrow phone, so the bar
wraps. That needed the children grouping first: with seven loose ones the break
could land anywhere, and stranding "Today" alone on a second line is worse than
not wrapping at all. The timers are one group and the day controls another, so
the wrap falls between them.

Two things follow from the bar changing height. The tab bar sticks to that
height, and the ResizeObserver added when the pill first appearing had the same
effect already covers it — nothing new needed. And both pills go to standby
together while the big card is on screen: standby is visibility, not display,
so the bar keeps its wrapped height while you scroll and the tab bar beneath it
does not shuffle.

The card shows the walk while there is one. It has room for a single timer, and
you are necessarily awake on a walk, so "awake for 3h" is the less useful of the
two readings; the bar keeps both. That also meant moving the card out of the
early return for "no sleep logged yet" — a walk can be the first thing ever
recorded, and the card was staying blank through it.
This commit is contained in:
Alexander Heldt
2026-09-08 20:46:04 +00:00
parent 7c0ccca1b2
commit fba0f73717
5 changed files with 155 additions and 36 deletions
+32 -3
View File
@@ -270,7 +270,13 @@ body::before {
gap: 6px;
align-items: center;
justify-content: flex-end;
flex-wrap: nowrap;
/* Wraps only when it has to — which on a narrow phone is while a walk is
running and there are two timers to fit. The two groups above are what
make that wrap land in a sensible place. The bar's height changes when it
does, and the tab bar sticks to that height, so a ResizeObserver keeps
--day-bar-h honest (see measureDayBar). */
flex-wrap: wrap;
row-gap: 6px;
padding: 8px 10px;
}
/* The face button shows the short date; the real input sits invisibly behind
@@ -309,15 +315,33 @@ body::before {
opacity: 0.4;
cursor: not-allowed;
}
/* The timers sit left, the day controls right. Both are groups so that when a
running walk makes the row too long the bar wraps between them, rather than
stranding "Today" on a line by itself. */
.bar-timers {
display: flex;
align-items: center;
gap: 6px;
margin-right: auto;
min-width: 0;
}
.day-nav {
display: flex;
align-items: center;
gap: 6px;
flex-shrink: 0;
}
/* An empty timer group must not hold a line open once it has wrapped. */
.bar-timers:empty { display: none; }
.bar-clock {
display: flex;
/* It is a button (tapping it flips the sleep state), so undo the default
accent look — the asleep/awake classes below paint it. */
accent look — the asleep/awake/walking classes below paint it. */
background: var(--surface);
color: var(--text);
align-items: center;
gap: 6px;
margin-right: auto; /* pin left; the flexible gap sits between it and the day controls */
padding: 7px 10px;
border-radius: 999px;
font-weight: 700;
@@ -333,6 +357,9 @@ body::before {
12% where asleep takes 18% — equal percentages of these two hues are not
equally strong, and yellow at 18% shouted while the blue did not. */
.bar-clock.awake { background: color-mix(in srgb, var(--wake) 12%, var(--surface)); color: var(--wake-timer-ink); }
/* The walk timer takes the walk colour the rest of the app already uses for
walks, so the pill says which of the two it is without needing its label. */
.bar-clock.walking { background: color-mix(in srgb, var(--walk) 16%, var(--surface)); color: var(--walk); }
.big-clock {
text-align: center;
@@ -362,6 +389,8 @@ body::before {
.big-clock.asleep .bc-time { color: var(--sleep-ink); }
.big-clock.awake { background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--wake) 10%, var(--surface))); }
.big-clock.awake .bc-time { color: var(--wake-timer-ink); }
.big-clock.walking { background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--walk) 10%, var(--surface))); }
.big-clock.walking .bc-time { color: var(--walk); }
/* Quick actions: a stack of explicit rows (see index.html) instead of one
auto-fit grid, so the grouping is the same at every width. Equal columns