diff --git a/src/app.js b/src/app.js index 2afebc1..97674c2 100644 --- a/src/app.js +++ b/src/app.js @@ -989,20 +989,27 @@ parts.push(`${vText}h`); } + const selYmd = ymd(selectedDay()); days.forEach((d, i) => { const isToday = i === days.length - 1; + const isSel = d.ymd === selYmd; const x = ML + i * (barW + gap); const h = (d.sleepHours / yMax) * innerH; const y = MT + innerH - h; const title = `${d.date.toLocaleDateString(undefined, { weekday: "long", month: "short", day: "numeric" })} — ${d.sleepHours.toFixed(1)}h`; + if (isSel) { + parts.push(``); + } parts.push( `` + `${escapeText(title)}` ); - if (showDayLabel(i, days.length)) { + // The selected day always gets a label (accent-colored), even on wide + // windows that would otherwise skip it. + if (showDayLabel(i, days.length) || isSel) { parts.push( - `` + + `` + `${escapeText(dayLabel(d.date, isToday))}` ); } @@ -1040,10 +1047,15 @@ { key: "meals", label: "Meals", cls: "bar-eat" }, ]; + const selYmd = ymd(selectedDay()); days.forEach((d, i) => { const isToday = i === days.length - 1; + const isSel = d.ymd === selYmd; const groupX = ML + i * (groupW + groupGap); + if (isSel) { + parts.push(``); + } series.forEach((s, j) => { const val = d[s.key]; const x = groupX + j * (barW + innerBarGap); @@ -1057,9 +1069,9 @@ ); }); - if (showDayLabel(i, days.length)) { + if (showDayLabel(i, days.length) || isSel) { parts.push( - `` + + `` + `${escapeText(dayLabel(d.date, isToday))}` ); } @@ -1095,20 +1107,25 @@ parts.push(`${vText}`); } + const selYmd = ymd(selectedDay()); days.forEach((d, i) => { const isToday = i === days.length - 1; + const isSel = d.ymd === selYmd; const x = ML + i * (barW + gap); const h = (d.grams / yMax) * innerH; const y = MT + innerH - h; const title = `${d.date.toLocaleDateString(undefined, { weekday: "long", month: "short", day: "numeric" })} — ${Math.round(d.grams)} g`; + if (isSel) { + parts.push(``); + } parts.push( `` + `${escapeText(title)}` ); - if (showDayLabel(i, days.length)) { + if (showDayLabel(i, days.length) || isSel) { parts.push( - `` + + `` + `${escapeText(dayLabel(d.date, isToday))}` ); } @@ -1157,15 +1174,17 @@ parts.push(`${hr}h`); } + const selYmd = ymd(selectedDay()); for (let i = 0; i < N; i++) { const day = new Date(today); day.setDate(day.getDate() - (N - 1 - i)); // oldest at top, today at bottom const dayStart = startOfDay(day).getTime(); const dayEnd = dayStart + dayMs; const isToday = ymd(day) === ymd(new Date()); + const isSel = ymd(day) === selYmd; const y = MT + i * (rowH + rowGap); - parts.push(``); + parts.push(``); for (const wdw of windows) { const s = Math.max(wdw.start, dayStart); @@ -1177,7 +1196,7 @@ } const label = isToday ? "Today" : `${day.toLocaleDateString(undefined, { weekday: "short" })} ${day.getDate()}`; - parts.push(`${escapeText(label)}`); + parts.push(`${escapeText(label)}`); const title = day.toLocaleDateString(undefined, { weekday: "long", month: "short", day: "numeric" }); parts.push(`${escapeText(title)}`); @@ -1584,6 +1603,13 @@ const cellW = innerW / N; const parts = []; + const selCol = dayIndex.get(ymd(selectedDay())); + if (selCol !== undefined) { + parts.push( + `` + ); + } exercises.forEach((x, r) => { const y = MT + r * (rowH + rowGap); const max = Math.max(1, ...counts[r]); diff --git a/src/changelog.json b/src/changelog.json index 9cbd70d..957c980 100644 --- a/src/changelog.json +++ b/src/changelog.json @@ -1,4 +1,5 @@ [ + { "date": "2026-07-15", "text": "The charts highlight the selected day, so it's easy to spot which bars, rows and cells you're looking at" }, { "date": "2026-07-15", "text": "New Sleep trend chart: today's running sleep total through the day, against yesterday and the average over your chart window (7/14/30 days)" }, { "date": "2026-07-15", "text": "Quick actions that don't fit right now are dimmed (asleep → everything but Sleep end; awake → Sleep end) — still tappable for corrections" }, { "date": "2026-07-15", "text": "Editing an event no longer pops the date picker over the whole screen on iPhone" }, diff --git a/src/style.css b/src/style.css index 0a88327..c68f044 100644 --- a/src/style.css +++ b/src/style.css @@ -603,6 +603,16 @@ dialog menu { } .chart-svg .bar { cursor: pointer; } .chart-svg .bar-faded { opacity: 0.7; } +/* The selected day's slice in every per-day chart: a soft accent band behind + the bars/cells (visible even when the day's values are all zero) plus an + accent-colored day label. */ +.chart-svg .day-highlight { + fill: var(--accent); + fill-opacity: 0.08; + stroke: var(--accent); + stroke-opacity: 0.45; +} +.chart-svg text.day-label-sel { fill: var(--accent); font-weight: 600; } .chart-svg .bar-sleep { fill: var(--sleep); } .chart-svg .bar-pee { fill: var(--pee); } .chart-svg .bar-poo { fill: var(--poo); } @@ -897,6 +907,13 @@ input.switch:checked::after { transform: translateX(18px); } } .chart-svg .stl-sleep { fill: var(--sleep); } .chart-svg .stl-today { fill: var(--accent); font-weight: 600; } +/* Selected day: accent ring on the row's track + accent label. */ +.chart-svg .stl-track.stl-selected { + stroke: var(--accent); + stroke-width: 1.2; + stroke-opacity: 0.8; +} +.chart-svg .stl-sel { fill: var(--accent); } .chart-svg .stl-hit { fill: transparent; cursor: pointer; } .chart-svg .stl-hit:hover { fill: var(--accent); fill-opacity: 0.08; }