Skip to content

feat(web): calendar week view as a drag-and-drop time-grid - #51

Merged
shottah merged 11 commits into
mainfrom
feat/calendar-timegrid
Jul 19, 2026
Merged

feat(web): calendar week view as a drag-and-drop time-grid#51
shottah merged 11 commits into
mainfrom
feat/calendar-timegrid

Conversation

@shottah

@shottah shottah commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Rebuilds the guide Calendar tab as a Google-Calendar-style time-grid, per docs/superpowers/specs/2026-07-18-calendar-timegrid-design.md. The Board tab is intentionally untouched (its overhaul is a separate future PR).

  • Shared time axis: a left gutter of hour labels; items positioned by start time and sized by duration (a 2-hour movie is twice the height of a 1-hour episode).
  • Vertical scale fills the viewport, floors at 66vh so a sparse week stays generous, and scrolls rather than crushing hours on a long day; each hour is equal height, driven entirely by CSS vars.
  • Overlapping items split their day into side-by-side sub-columns (pure column-packing, unit-tested; touching edges do not split).
  • Time moves to the gutter, so the per-item time pill is gone and cards reclaim that space; poster tint, hover glow, quick-actions, Pinned badge, and the drill-in menu all stay.
  • Drag-and-drop (@dnd-kit): vertical movement re-times an item (snapped to 15 min), the drop column re-days it, landed with an optimistic PATCH that rolls back on rejection. Keyboard-draggable for a11y; a 6px activation distance keeps the click-to-open menu working.
  • Past-move rules, which did not exist before, are now enforced server-side (new 422s) and gated client-side: a past slot can't be moved and nothing can be moved into the past. The per-day window still gates only generate, never a manual move.

New deps: @dnd-kit/core, @dnd-kit/modifiers.

Verification: per-task reviews (one caught a coupled-conditional-style fixture typo; one hardened a DateStyle-dependent date cast on the enforcement path) plus a final whole-branch review with a live-wire smoke on isolated data confirming future->future move 200, past-slot move 422, move-into-past 422, and window-violating-but-valid move 200.

Not merged yet: held for a manual drag-feel pass on the live stack (both servers serve this branch). Actual pixel snap, cross-day drop, keyboard drag, and the rollback animation are the things to feel.

https://claude.ai/code/session_01VJLReS68zKnpPZgGrbfdLa

shottah added 11 commits July 18, 2026 14:45
Rewrites the Calendar tab into a static time-grid: a shared TimeGutter
axis plus 7 DayColumns, each item absolutely positioned by
topFactor/spanFactor/colIndex/colCount from toTimeGrid (#18 Task 3).
GridItemCard is the poster-tinted card minus the time pill, still
wiring ItemMenu/SlotQuickActions unchanged. No drag yet (Task 4);
moves go through the existing Move picker.

Claude-Session: https://claude.ai/code/session_01VJLReS68zKnpPZgGrbfdLa
Past guide items are non-draggable (useDraggable disabled), but the
inner click-to-open button still carried dnd-kit's attributes spread —
including aria-disabled="true" and aria-roledescription="draggable" —
even though the button remains fully clickable (opening ItemMenu on a
past item is intentional). Screen readers would announce the button as
disabled while it still works. Only spread listeners/attributes when the
card is draggable; past cards render a plain, correctly-labeled button.

Claude-Session: https://claude.ai/code/session_01VJLReS68zKnpPZgGrbfdLa
…ength

SwapTitle returned the raw titles.runtime_minutes (0 for back-catalog
titles TMDB reports no runtime for), so a swap set DurationMin=0 and
UpdateGuideItem computed end_min=start_min — a zero-length slot. The
generation path already applied the 45/120 default; extract it into a
shared defaultRuntime helper and route both paths through it. The old
fixed-height calendar hid the collapse; the time-grid renders it as a
min-height pill, which surfaced the bug.

Claude-Session: https://claude.ai/code/session_01VJLReS68zKnpPZgGrbfdLa
@shottah

shottah commented Jul 19, 2026

Copy link
Copy Markdown
Owner Author

Added a fix while validating a bug found during manual testing (7d9e218): swapped-in items were collapsing to zero height in the time-grid. Root cause was pre-existing and unrelated to the grid itself; SwapTitle returned the raw titles.runtime_minutes (0 for back-catalog titles TMDB reports no runtime for) instead of applying the 45/120 default the generation path already uses, so a swap set DurationMin=0 and the item became a zero-length slot. The old fixed-height calendar hid it; the duration-sized grid surfaced it. Extracted a shared defaultRuntime helper so both paths agree, plus a store test. Also repaired the four already-corrupted rows in the affected guide directly (they were kept across regenerate, so they wouldn't self-heal).

@shottah
shottah merged commit 209302c into main Jul 19, 2026
2 checks passed
@shottah
shottah deleted the feat/calendar-timegrid branch July 19, 2026 22:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant