From 83af641a1297540af9a1ee441aa339b1c527f878 Mon Sep 17 00:00:00 2001 From: Alexander Heldt Date: Wed, 15 Jul 2026 10:56:16 +0000 Subject: [PATCH] Use 1-hour gridlines on the daily Sleep bar chart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit niceAxisSleepHours drops from 2-hour to 1-hour steps and is shared with the trend chart again (the trend-only helper it duplicated is gone). Labels thin to every other gridline past 12 steps — this chart's plot area is shorter than the trend's. --- src/app.js | 25 +++++++++++-------------- src/changelog.json | 1 + 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/app.js b/src/app.js index d243ee6..9d0be5e 100644 --- a/src/app.js +++ b/src/app.js @@ -941,12 +941,12 @@ return { yMax, steps: Math.max(1, Math.round(yMax / step)) }; } - // Sleep-specific axis: always 2-hour granularity, capped at 24h/day, - // for a more readable picture of typical 10–18 h puppy sleep. + // Sleep-specific axis: 1-hour granularity, capped at 24h/day. Shared by the + // sleep bars and the trend chart; both thin out labels when steps get dense. function niceAxisSleepHours(rawMax) { if (!(rawMax > 0)) return { yMax: 2, steps: 2 }; - const m = Math.min(24, Math.max(2, Math.ceil(rawMax / 2) * 2)); - return { yMax: m, steps: m / 2 }; + const m = Math.min(24, Math.max(2, Math.ceil(rawMax))); + return { yMax: m, steps: m }; } function escapeText(s) { @@ -980,13 +980,18 @@ const gap = days.length > 14 ? 2 : 4; const barW = (innerW - (days.length - 1) * gap) / days.length; + // Every gridline gets a label unless that would crowd the 9px text + // (this chart's plot area is shorter than the trend chart's). + const labelEvery = ySteps > 12 ? 2 : 1; const parts = []; for (let i = 0; i <= ySteps; i++) { const y = MT + innerH * (1 - i / ySteps); const v = Math.round(yMax * i / ySteps * 10) / 10; const vText = v % 1 === 0 ? v : v.toFixed(1); parts.push(``); - parts.push(`${vText}h`); + if (i % labelEvery === 0) { + parts.push(`${vText}h`); + } } const selYmd = ymd(selectedDay()); @@ -1341,14 +1346,6 @@ return { today, yesterday, avg, avgDays, projected }; } - // Trend-specific y-axis: 1-hour gridlines (vs the bar charts' 2-hour steps) - // so nearby curves separate visually; still capped at 24h. - function niceAxisTrendHours(rawMax) { - if (!(rawMax > 0)) return { yMax: 2, steps: 2 }; - const m = Math.min(24, Math.max(2, Math.ceil(rawMax))); - return { yMax: m, steps: m }; - } - function drawSleepTrendChart(curves) { const svg = document.getElementById("chart-sleep-trend"); if (!svg) return; @@ -1366,7 +1363,7 @@ ].filter(s => s.pts && s.pts.length > 1); const rawMax = Math.max(...series.flatMap(s => s.pts.map(p => p.y))); - const { yMax, steps: ySteps } = niceAxisTrendHours(rawMax); + const { yMax, steps: ySteps } = niceAxisSleepHours(rawMax); const xOf = (hour) => ML + (hour / 24) * innerW; const yOf = (v) => MT + innerH * (1 - v / yMax); diff --git a/src/changelog.json b/src/changelog.json index 7936d35..fd5817d 100644 --- a/src/changelog.json +++ b/src/changelog.json @@ -1,4 +1,5 @@ [ + { "date": "2026-07-15", "text": "The Sleep chart in the last-N-days card now has 1-hour gridlines too" }, { "date": "2026-07-15", "text": "The Sleep trend chart is taller with 1-hour gridlines, so nearby lines are easier to tell apart" }, { "date": "2026-07-15", "text": "The Sleep trend legend shows the hours for each line — Today, Yesterday and the average, next to the projection" }, { "date": "2026-07-15", "text": "The Sleep trend chart projects where today will land by midnight — a dashed tail continues today's line following the average day's rhythm" },