Group the charts by subject, not by window

"Last 7 days" collected four charts for no better reason than sharing an axis,
which put sleep hours a full panel away from the two sleep patterns and the
counts chart nowhere near the by-hour view of the same events.

Each chart now sits with its subject. Sleep hours per day becomes its own Sleep
panel directly above the sleep timeline, so the three sleep views read in
sequence. Daily counts and Food join the heatmap in one "Pees, poos & meals"
panel: how many a day, how much food went with them, and what hours they fall
in are three views of one set of events and belong on one card. Minutes walked
per day goes to the Walks panel, which is the same move applied to the chart
the split didn't mention.

The day-window picker stays a single control, in the Sleep panel, because it
was never scoped to the panel holding it — it drives the training grid, both
sleep patterns and the counts panel too. That is unchanged, and the panel it
lives in occupies the slot the old one did, so it has not moved on screen. A
comment says so, since a global control sitting inside one card does not
announce itself. Duplicating it into each panel would work as-is (both the
labels and the buttons are addressed by querySelectorAll) if reaching it ever
becomes a scroll.

Both new panels take new data-panel keys, so anyone who had the old panels
folded gets the new ones open rather than inheriting a collapse they chose for
something else. The dead #daily-charts-title lookup goes with the heading.
This commit is contained in:
Alexander Heldt
2026-08-31 21:51:33 +00:00
parent 7a1c0f3808
commit e037ab2716
4 changed files with 38 additions and 27 deletions
-2
View File
@@ -1258,8 +1258,6 @@
// Sync every "(last N days)" header and the picker's active button. // Sync every "(last N days)" header and the picker's active button.
function renderChartWindow() { function renderChartWindow() {
const n = chartDays(); const n = chartDays();
const title = document.getElementById("daily-charts-title");
if (title) title.textContent = `Last ${n} days`;
document.querySelectorAll("[data-chart-days-label]").forEach(el => { document.querySelectorAll("[data-chart-days-label]").forEach(el => {
el.textContent = `(last ${n} days)`; el.textContent = `(last ${n} days)`;
}); });
+1
View File
@@ -1,4 +1,5 @@
[ [
{ "date": "2026-08-31", "text": "The charts are grouped by subject instead of all sharing one “Last 7 days” panel. Sleep hours per day is now its own Sleep panel, sitting just above the “When … sleeps” timeline with the rest of the sleep views. Daily counts and Food have joined the by-hour chart in one “Pees, poos & meals” panel, so how many a day, how much food went with them and what hours they fall in read together. Minutes walked per day has moved into the Walks panel. The 7d / 14d / 30d picker now sits in the Sleep panel and still sets the window for every one of these charts" },
{ "date": "2026-08-31", "text": "A sleep or walk pair is now tied together in the History log by a dotted rail down the side, in that pair's colour, running from the start row to the end row. Anything logged in between sits inside the bracket, so a pee taken on a walk reads as having happened during it. A pair still in progress, or one that ran over from yesterday, leaves its end of the rail open" }, { "date": "2026-08-31", "text": "A sleep or walk pair is now tied together in the History log by a dotted rail down the side, in that pair's colour, running from the start row to the end row. Anything logged in between sits inside the bracket, so a pee taken on a walk reads as having happened during it. A pair still in progress, or one that ran over from yesterday, leaves its end of the rail open" },
{ "date": "2026-08-31", "text": "Added walks: tap 🦮 Walk start when you head out and 🏁 Walk end when you get home, and the time in between is counted as exercise. The pair gets its own row under the sleep buttons. Today's total and the number of walks show in the overview, every walk of the day is listed in a new Walks section (with the age-based rule of thumb of about five minutes per month of age, twice a day), and the daily charts gain a “Walks (minutes)” bar chart once you have logged one. Like sleep, only the boundary that makes sense is tappable — no walk running means Walk end is greyed out" }, { "date": "2026-08-31", "text": "Added walks: tap 🦮 Walk start when you head out and 🏁 Walk end when you get home, and the time in between is counted as exercise. The pair gets its own row under the sleep buttons. Today's total and the number of walks show in the overview, every walk of the day is listed in a new Walks section (with the age-based rule of thumb of about five minutes per month of age, twice a day), and the daily charts gain a “Walks (minutes)” bar chart once you have logged one. Like sleep, only the boundary that makes sense is tappable — no walk running means Walk end is greyed out" },
{ "date": "2026-08-31", "text": "The Log event buttons are grouped into rows now instead of flowing into one grid: 😴 Sleep start and ⏰ Sleep end side by side on their own row, then 💧 Pee and 💩 Poo, and last the three that ask for a value — 🍽️ Ate / ⚖️ Weight / 📝 Note — three across. The two halves of a sleep pair can no longer end up split across a wrap, and no button is left stranded alone on the last row. The weigh-in button is now just ⚖️ Weight, which fits the narrower slot; weigh-ins read as “Weight” in the history log to match" }, { "date": "2026-08-31", "text": "The Log event buttons are grouped into rows now instead of flowing into one grid: 😴 Sleep start and ⏰ Sleep end side by side on their own row, then 💧 Pee and 💩 Poo, and last the three that ask for a value — 🍽️ Ate / ⚖️ Weight / 📝 Note — three across. The two halves of a sleep pair can no longer end up split across a wrap, and no button is left stranded alone on the last row. The weigh-in button is now just ⚖️ Weight, which fits the narrower slot; weigh-ins read as “Weight” in the history log to match" },
+31 -22
View File
@@ -237,36 +237,27 @@
<!-- Age-based guidance ("the five-minute rule"), only when a birthday <!-- Age-based guidance ("the five-minute rule"), only when a birthday
is set and the puppy is still growing. --> is set and the puppy is still growing. -->
<p id="walk-goal" class="muted-note" hidden></p> <p id="walk-goal" class="muted-note" hidden></p>
<div class="chart walk-chart" id="walk-chart-wrap" hidden>
<div class="chart-title">Minutes per day <span data-chart-days-label>(last 7 days)</span></div>
<svg id="chart-walk" class="chart-svg" viewBox="0 0 320 160" role="img" aria-label="Minutes walked per day"></svg>
</div>
</section> </section>
<section class="weekly" data-panel="weekly"> <!-- The day-window picker lives in this panel but governs every
<h2 id="daily-charts-title">Last 7 days</h2> day-window chart on the page — the training grid above, both sleep
patterns below, the counts panel and the walk chart — so changing it
here changes all of them (see renderChartWindow). -->
<section class="patterns" data-panel="sleep-daily">
<h2>Sleep <span class="muted-note" data-chart-days-label>(last 7 days)</span></h2>
<div class="chart-days-picker" role="group" aria-label="How many days the charts cover"> <div class="chart-days-picker" role="group" aria-label="How many days the charts cover">
<button type="button" class="ghost" data-days="7">7d</button> <button type="button" class="ghost" data-days="7">7d</button>
<button type="button" class="ghost" data-days="14">14d</button> <button type="button" class="ghost" data-days="14">14d</button>
<button type="button" class="ghost" data-days="30">30d</button> <button type="button" class="ghost" data-days="30">30d</button>
</div> </div>
<div class="chart"> <div class="chart">
<div class="chart-title">Sleep (hours)</div> <div class="chart-title">Hours per day</div>
<svg id="chart-sleep" class="chart-svg" viewBox="0 0 320 160" role="img" aria-label="Sleep hours per day"></svg> <svg id="chart-sleep" class="chart-svg" viewBox="0 0 320 160" role="img" aria-label="Sleep hours per day"></svg>
</div> </div>
<div class="chart">
<div class="chart-title">Daily counts</div>
<svg id="chart-counts" class="chart-svg" viewBox="0 0 320 180" role="img" aria-label="Pee, poo and meal counts per day"></svg>
<div class="legend legend-toggle" id="counts-metrics" role="group" aria-label="Which counts to show">
<label class="lg pee"><input type="checkbox" data-metric="pees" checked /><span class="sw"></span>Pees</label>
<label class="lg poo"><input type="checkbox" data-metric="poos" checked /><span class="sw"></span>Poos</label>
<label class="lg eat"><input type="checkbox" data-metric="meals" checked /><span class="sw"></span>Meals</label>
</div>
</div>
<div class="chart" id="walk-chart-wrap" hidden>
<div class="chart-title">Walks (minutes)</div>
<svg id="chart-walk" class="chart-svg" viewBox="0 0 320 160" role="img" aria-label="Minutes walked per day"></svg>
</div>
<div class="chart" id="grams-chart-wrap" hidden>
<div class="chart-title">Food (grams)</div>
<svg id="chart-grams" class="chart-svg" viewBox="0 0 320 160" role="img" aria-label="Grams of food eaten per day"></svg>
</div>
</section> </section>
<section class="patterns" data-panel="sleep-timeline"> <section class="patterns" data-panel="sleep-timeline">
@@ -288,11 +279,29 @@
<p class="muted-note">Hours slept so far at each point of the day, against yesterday and the average over the picked chart window. The dashed tail continues today's line the way the average day usually plays out. The axis is stretched above 10h to give the hours around the goal more room.</p> <p class="muted-note">Hours slept so far at each point of the day, against yesterday and the average over the picked chart window. The dashed tail continues today's line the way the average day usually plays out. The axis is stretched above 10h to give the hours around the goal more room.</p>
</section> </section>
<section class="patterns" data-panel="hour-heatmap"> <!-- One panel for the three views of the same events: how many a day,
<h2>By hour of day <span class="muted-note" data-chart-days-label>(last 7 days)</span></h2> how much food went with them, and what hours they fall in. -->
<section class="patterns" data-panel="counts">
<h2>Pees, poos &amp; meals <span class="muted-note" data-chart-days-label>(last 7 days)</span></h2>
<div class="chart">
<div class="chart-title">Daily counts</div>
<svg id="chart-counts" class="chart-svg" viewBox="0 0 320 180" role="img" aria-label="Pee, poo and meal counts per day"></svg>
<div class="legend legend-toggle" id="counts-metrics" role="group" aria-label="Which counts to show">
<label class="lg pee"><input type="checkbox" data-metric="pees" checked /><span class="sw"></span>Pees</label>
<label class="lg poo"><input type="checkbox" data-metric="poos" checked /><span class="sw"></span>Poos</label>
<label class="lg eat"><input type="checkbox" data-metric="meals" checked /><span class="sw"></span>Meals</label>
</div>
</div>
<div class="chart" id="grams-chart-wrap" hidden>
<div class="chart-title">Food (grams)</div>
<svg id="chart-grams" class="chart-svg" viewBox="0 0 320 160" role="img" aria-label="Grams of food eaten per day"></svg>
</div>
<div class="chart">
<div class="chart-title">By hour of day</div>
<svg id="chart-hour-heatmap" class="chart-svg" viewBox="0 0 320 120" role="img" aria-label="Pee, poo and meal frequency by hour of day"></svg> <svg id="chart-hour-heatmap" class="chart-svg" viewBox="0 0 320 120" role="img" aria-label="Pee, poo and meal frequency by hour of day"></svg>
<p id="hour-heatmap-info" class="muted-note hour-point-info" aria-live="polite"></p> <p id="hour-heatmap-info" class="muted-note hour-point-info" aria-live="polite"></p>
<p class="muted-note">Darker = happens more often at that hour.</p> <p class="muted-note">Darker = happens more often at that hour.</p>
</div>
</section> </section>
<section class="weight" data-panel="weight"> <section class="weight" data-panel="weight">
+3
View File
@@ -1164,7 +1164,10 @@ button.ex-log {
button.ex-edit { padding: 6px 12px; flex-shrink: 0; } button.ex-edit { padding: 6px 12px; flex-shrink: 0; }
.training-add { width: 100%; } .training-add { width: 100%; }
/* Charts that sit under a panel's list rather than being the whole panel, so
they need the separation a list-then-chart stack doesn't get for free. */
.training-chart { margin-top: 16px; } .training-chart { margin-top: 16px; }
.walk-chart { margin-top: 16px; }
/* ---------- collapsible panels ---------- */ /* ---------- collapsible panels ---------- */
section.collapsible > h2 { section.collapsible > h2 {