Make the day-bar sleep pill a one-tap toggle

Once the big timer scrolls away, the pill in the day bar is the only thing
still showing the sleep state — but acting on it meant scrolling back up to
the quick actions. Tapping the pill now logs the boundary that ends the state
it displays: sleep-end while asleep, sleep-start while awake. It routes
through quickLog(), so the snackbar and its undo behave exactly as they do
from the buttons, and the state is read from currentSleepState() rather than
the cached bigClockState so a tap can't act on a stale render.

The pill becomes a real <button>, which brings keyboard operation along for
free. In standby it is visibility:hidden, so while the big card is on screen
it is neither clickable nor tab-reachable, and the toggle is live exactly when
the pill is visible.

The .day-bar button padding and :disabled rules are scoped to :not(.bar-clock)
so they don't start outranking the pill's own sizing, and the default accent
button background is reset since the asleep/awake classes paint it.
This commit is contained in:
Alexander Heldt
2026-08-21 06:35:53 +00:00
parent 51d015c231
commit d81c20ac9b
4 changed files with 26 additions and 7 deletions
+13 -1
View File
@@ -781,7 +781,9 @@
ptime.textContent = counter;
since.textContent = `since ${formatTime(ts)}`;
icon.textContent = state === "asleep" ? "😴" : "☀️";
pill.title = `${state === "asleep" ? "Asleep" : "Awake"} since ${formatTime(ts)}`;
const flip = state === "asleep" ? "Sleep end" : "Sleep start";
pill.title = `${state === "asleep" ? "Asleep" : "Awake"} since ${formatTime(ts)} — tap to log ${flip.toLowerCase()}`;
pill.setAttribute("aria-label", `${state === "asleep" ? "Asleep" : "Awake"} since ${formatTime(ts)}. Log ${flip.toLowerCase()}.`);
updateBarClockMode();
}
@@ -3674,6 +3676,16 @@
});
});
// The timer pill doubles as a one-tap sleep toggle: tapping it logs the
// boundary that ends the state it shows, exactly like the matching quick
// action. Only reachable once the big card has scrolled away — in standby
// the pill is visibility:hidden, so clicks can never land on it.
document.getElementById("bar-clock").addEventListener("click", () => {
const { state } = currentSleepState(live());
if (!state) return; // no sleep history yet; the pill is hidden anyway
quickLog(state === "asleep" ? "sleep-end" : "sleep-start");
});
document.querySelectorAll(".chart-days-picker button").forEach(b => {
b.addEventListener("click", () => setChartDays(Number(b.dataset.days)));
});