Give the plays-per-day bars a track of their own

The tallest bars hung below the baseline the rest stood on. A bar's height is a percentage, and it shared one 6em flex box with the count and weekday under it, so any bar tall enough to overflow that box made flex shrink both it and the labels - a 100% bar rendered 67px instead of 96, and the shorter labels let its bottom edge slip 5px past where every other bar ended. The chart is a grid now: a 6em row for the bars and a row each for the two labels, with every <li> a subgrid spanning all three. The percentage resolves against a track with a height of its own, and the labels can't push the bar around. Measured over counts of 1-5, the bars go 25/50/75/ 100/125px on one baseline, where they used to go 19/38/58/65/67px on three. That exposed a second problem in the labels: at 375px a column is 19.3px and "Thu" needs 22, so every weekday was clipped mid-letter. The chart is a CSS container now, and a column too narrow for three letters falls back to the day's initial - the full date is on the column's title either way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

author
Marijn Besseling <njirambem@gmail.com> · 2026-09-09 15:41 UTC
commit
dfe928fa1573d0e083b63c7fa93772f039111688
parent
49a27c0aeb
tree
browse at this commit

3 files changed +50 -12

Blog/Components/Pages/Rvrb.razor +1 -1

@@ -143,7 +143,7 @@
143 143 <li title="@BarTitle(day)">
144 144 <span class="bar" style="block-size: @(BarHeight(day.Plays))%"></span>
145 145 <span class="bar-label">@day.Plays</span>
146 - <span class="bar-day">@DayLabel(day)</span>
146 + <span class="bar-day"><span class="day-abbrev">@DayLabel(day)</span><span class="day-initial">@DayInitial(day)</span></span>
147 147 </li>
148 148 }
149 149 </ol>

Blog/Components/Pages/Rvrb.razor.cs +7 -0

@@ -58,6 +58,13 @@ public partial class Rvrb : ComponentBase
58 58 private static string DayLabel(RvrbDay day) => day.Date.ToString("ddd", CultureInfo.InvariantCulture);
59 59
60 60 /// <summary>
61 + /// The same weekday as a single letter, for a chart too narrow to give each day three of them.
62 + /// Ambiguous on its own — T is Tuesday or Thursday — but the column carries the full date in
63 + /// its title, and the alternative at that width is a clipped abbreviation.
64 + /// </summary>
65 + private static string DayInitial(RvrbDay day) => DayLabel(day)[..1];
66 +
67 + /// <summary>
61 68 /// A day's bar height as a percentage of the busiest day in the window, floored at something
62 69 /// visible so a day with one play doesn't render as nothing at all.
63 70 /// </summary>

Blog/wwwroot/app.css +42 -11

@@ -615,24 +615,37 @@ progress {
615 615 }
616 616
617 617 /* Plays per day. One <li> per day, so a quiet day is an empty column rather
618 - than a gap - see Rvrb.Stats.plays_per_day/1. */
618 + than a gap - see Rvrb.Stats.plays_per_day/1.
619 +
620 + A grid rather than a flex row, because a bar's height is a percentage and
621 + can only resolve against a track with a height of its own. Sharing one 6em
622 + box with the labels made the two compete for it: flex shrank whichever bar
623 + was tall enough to overflow *and* the labels under it, so the tallest bars
624 + ended up hanging below the baseline the rest stood on. */
619 625 .bars {
620 - display: flex;
621 - align-items: end;
622 - gap: var(--border-width);
623 - block-size: 6em;
626 + /* A container, so the labels below can react to how much room each column
627 + actually got rather than to the width of the viewport. */
628 + container-type: inline-size;
629 + display: grid;
630 + grid-auto-flow: column;
631 + grid-auto-columns: 1fr;
632 + /* the bar track, then a row each for the count and the weekday */
633 + grid-template-rows: 6em auto auto;
634 + /* Column gap only: the labels belong against the bar they describe. */
635 + gap: 0 var(--border-width);
624 636 margin-block: 0;
625 637 padding-inline: 0;
626 638 list-style: none;
627 639 }
628 640
641 +/* subgrid, so every column's count and weekday line up on the same two rows
642 + however tall the bar above them is. */
629 643 .bars li {
630 - display: flex;
631 - flex: 1;
632 - flex-direction: column;
633 - align-items: center;
634 - justify-content: end;
635 - block-size: 100%;
644 + display: grid;
645 + grid-row: span 3;
646 + grid-template-rows: subgrid;
647 + align-items: end;
648 + justify-items: center;
636 649 }
637 650
638 651 .bars .bar {
@@ -655,6 +668,24 @@ progress {
655 668 white-space: nowrap;
656 669 }
657 670
671 +.bars .day-initial {
672 + display: none;
673 +}
674 +
675 +/* "Thu" wants about 3.2ch, so a fortnight of them needs roughly this much
676 + chart before the columns stop being wide enough to hold three letters. On a
677 + phone they don't, and the day falls back to its initial rather than being
678 + clipped mid-letter. */
679 +@container (width < 21rem) {
680 + .bars .day-abbrev {
681 + display: none;
682 + }
683 +
684 + .bars .day-initial {
685 + display: inline;
686 + }
687 +}
688 +
658 689
659 690 /* -- Storage ------------------------------------------------------------- */
660 691