Components · Calendar

Week time-grid

The calendar engine's WeekView — the seven weekDays laid over a dayHours() axis (6 AM → 11 PM, HOUR_PX = 48). Timed events become absolutely-positioned blocks: top = minutes since the grid start, height = duration. Overlapping events are lane-packed side-by-side (packLanes greedy interval colouring) so concurrent items sit beside each other and stay clickable. Point-in-time / out-of-window events surface in the per-day all-day strip; today carries the "now" line.

Calendar view="week" · Jun 28 – Jul 4, 2026 · note Thursday's 3-lane overlap
Sun
28
Mon
29
Tue
30
Wed
1
Thu
2
Fri
3
Sat
4
Kennel deep-clean8:00 – 10:00 AM
Transport team sync5:00 – 6:00 PM
Foster orientation6:00 – 7:30 PM
Adoption prep10:00 – 11:00 AM
Supply pickup1:00 – 2:00 PM
Transport — Bakersfield8:30 – 10:00 AM
Foster check-in — Luna9:00 – 10:30 AM
Intake photos
Vaccine clinic11:30 AM – 1:00 PM
Phone bank — spay/neuter2:30 – 4:00 PM
Mobile adoption — Riverside9:00 AM – 12:00 PM
Leash walk & meet4:00 – 5:30 PM
Adoption Day — Fetch Park10:00 AM – 3:00 PM

Thursday (today) shows the lane-packer at work: Transport (pinned :hover), Foster check-in, and Intake photos overlap 9:00–10:00, so all three share a cluster and each takes width = 1/3 at left = lane/3 — beside, never behind. The accent now line sits at 12:20 PM. Independence Day rides the Sat all-day strip. Major spans (isMajor) underline their title; tone is accent · good · warn · bad · neutral.

time axis
dayHours() → 6 AM–11 PM, one 48px row each (HOUR_PX). Blocks scroll in a max-h-[60vh] area; MIN_BLOCK_PX = 18 floors very short events.
split
splitDayEvents clamps each event to the day from the midnight boundary; timed slices that intersect the window become blocks, everything else drops to the all-day strip on every day it covers.
lane packing
packLanes — greedy interval colouring. Each event takes the lowest free lane; a contiguous overlap cluster stamps every member with its laneCount so widths divide evenly (width = 1/laneCount, left = lane/laneCount).
today / now
Today's column gets a 5% accent wash + aria-current="date"; a 1px accent line with a dot marks the current minute when it's inside the 6 AM–11 PM window.
EventChip
variant="block" — a 2px left tone border, title (isMajor underlined) + time range; variant="strip" for the compact all-day pill. Link when href, else fires onSelectEvent.

Source · ds/calendar/WeekView.tsx (EventChip block/strip, toneChip) · placement.ts (packLanes, splitDayEvents, placeTimed) · date-utils.ts (weekDays, dayHours, fmtTime) · composed by Calendar.tsx.