Fix trapped scrollbars app-wide, keep the week calendar as its own scroll

Several overflow-x-auto wrappers (table cards, a text preview) got an
accidental *vertical* scrollbar too -- per the CSS overflow spec, setting
only overflow-x to a non-visible value forces the other axis to compute as
auto if left unset, so any of these taller than the viewport were trapped
scrolling independently of the page (Safari showed it plainly; other
browsers hid it more subtly). Fixed everywhere with overflow-y-visible,
except the week calendar.

The week grid genuinely needs to stay its own bounded, contained scroll:
it always spans the full 24h day (never clipped, by design), so folding it
into the page's own scroll would mean scrolling past a screenful of empty
early hours most weeks. Instead it's capped to 70vh with a real
overflow-y-auto, and a small script scrolls it to just before the week's
first event on load (events.services.calendar.week_grid now reports
first_event_hour) -- no more landing on an empty view by default.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
This commit is contained in:
2026-08-22 19:13:28 +02:00
parent ae8e4c411d
commit 86ea8d1b15
13 changed files with 89 additions and 11 deletions

View File

@@ -158,6 +158,12 @@ def week_grid(events, week_start: datetime.date) -> dict:
"hours": list(range(day_start_hour, day_end_hour + 1)),
"day_start_hour": day_start_hour,
"day_end_hour": day_end_hour,
# The grid always spans the full day (see DEFAULT_DAY_START_HOUR/END_HOUR's
# own comment -- never clipped), so a plain "top of the grid" scroll position
# would default to an empty 00:00 view most weeks. The template scrolls its
# bounded viewport to just before this hour instead -- None when the week has
# no events at all, since there's nothing to reveal either way.
"first_event_hour": min((start.hour for _event, start, _end in spans), default=None),
}

View File

@@ -1708,6 +1708,22 @@ class CalendarGridTests(EventsTestBase):
self.assertEqual(grid["day_start_hour"], 0)
self.assertEqual(grid["day_end_hour"], 24)
def test_week_grid_first_event_hour_is_the_earliest_events_start_hour(self):
monday = date(2026, 8, 17)
morning = self.make_event(title="Morning", start=self.at(monday, 9), end=self.at(monday, 10))
evening = self.make_event(title="Evening", start=self.at(monday + timedelta(days=2), 18), end=self.at(monday + timedelta(days=2), 19))
grid = week_grid([morning, evening], monday)
self.assertEqual(grid["first_event_hour"], 9)
def test_week_grid_first_event_hour_is_none_when_the_week_has_no_events(self):
monday = date(2026, 8, 17)
grid = week_grid([], monday)
self.assertIsNone(grid["first_event_hour"])
def test_week_grid_excludes_events_outside_the_week(self):
monday = date(2026, 8, 17)
event = self.make_event(start=self.at(monday + timedelta(days=7), 10))