Resize glitches on calendar widget (aspect ratio + odd sizes) #18
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_whiteboard#18
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Calendar widget loses aspect ratio during resize drag (self-corrects on release), and renders broken at odd sizes.
Implementation Spec for Issue #18
Objective
Make the calendar widget render correctly both while the resize is in progress (no aspect-ratio distortion of children) and at any aspect ratio allowed by the transformer (no row/column overlap at short heights or narrow widths).
Root-cause analysis
scaleX/scaleYto the calendar Group during a resize drag. Every child (bg, header, date text, grid lines) is visually stretched/squished untiltransformend, whereWhiteboardObjects.applyTransformresetsscaleto 1 andWhiteboardCalendar.redrawrebuilds the layout at the new width/height. The "self-corrects on release" effect the user reported is exactly this deferred redraw.keepRatio: falsein the transformer andMath.max(240, …) / Math.max(200, …)as the only clamp in objects.js:1041-1042, the month view (calendar.js:234) computescellH = (contentH - 20) / 6. When the user stretches the calendar very wide and short,contentHbecomes small enough thatcellHis smaller than the 11 px date text, so all 5-6 week rows collapse on top of each other. The minimum clamp is also not view-aware: month needs a tall-enough box to show 6 weeks; day view needs even more for 14 hour rows; week view wants width.Requirements
_calStateshape, undo/redo, nav arrows, or multi-user sync.Files to Modify
crates/hero_whiteboard_ui/static/web/js/whiteboard/tools.js— add atransformer.on('transform', ...)handler that, for each calendar node currently being transformed, live-applies scaled dimensions to the bg and callsWhiteboardCalendar.redraw(node)so the user sees correct layout during the drag.crates/hero_whiteboard_ui/static/web/js/whiteboard/objects.js— replace the hardcodedMath.max(240, …) / Math.max(200, …)in thecalendarbranch ofapplyTransformwith view-aware minimums read from a helper incalendar.js. Keep the same code path fortransformendso both live redraw (Step 1) and final redraw use the same clamp.crates/hero_whiteboard_ui/static/web/js/whiteboard/calendar.js— expose agetMinSize(viewMode)helper and hardenrenderMonthViewsocellHnever drops below the text height (defensive floor so a manual bg.width/height write from elsewhere cannot reintroduce the overlap).Implementation Plan
Step 1: Live redraw during calendar transform
Files:
crates/hero_whiteboard_ui/static/web/js/whiteboard/tools.js,crates/hero_whiteboard_ui/static/web/js/whiteboard/calendar.jstransformevent listener on the transformer (next to the existingtransformstart/transformendhandlers) that iterates the transformer's nodes and, for each one namedobject calendar:scaleX/scaleYon the node..bg, computenewW = bg.width() * scaleX,newH = bg.height() * scaleY, clamp to the view-aware minimum (see Step 2).bg.width(newW)/bg.height(newH), resetnode.scaleX(1)/node.scaleY(1)so the nexttransformevent starts from the clamped box instead of compounding the scale.WhiteboardCalendar.redraw(node)so children re-lay-out at the live dimensions.transformer.forceUpdate()at the end of the iteration so the outline tracks the clamped box.calendar.js, ensureredrawis cheap enough to call ~60 Hz.renderCalendaralready doesgroup.destroyChildren()+ a small number of Konva node creations; this is acceptable. Add aname: 'bg'to the bg creation if not already present (it is — line 76). No changes needed here for this step beyond defininggetMinSize(Step 2).Dependencies: Step 2 for the helper, but they can be landed in the same pass; order the edits as Step 2 first so
getMinSizeis available when Step 1 references it.Step 2: View-aware minimum size clamp
Files:
crates/hero_whiteboard_ui/static/web/js/whiteboard/calendar.js,crates/hero_whiteboard_ui/static/web/js/whiteboard/objects.jscalendar.js, add agetMinSize(viewMode)function returning{ minW, minH }:month:{ minW: 280, minH: 260 }— 7 day columns + 6 week rows need at least this to stay readable.week:{ minW: 320, minH: 220 }— 7 day columns + 12 hour rows.day:{ minW: 200, minH: 280 }— single-column day view with 14 hour rows.{ minW: 240, minH: 200 }.getMinSizefrom the module return.objects.js, replace thecalendarbranch ofapplyTransform:Dependencies: none (lands before Step 1 to satisfy its reference).
Step 3: Defensive floor on month-view row height
Files:
crates/hero_whiteboard_ui/static/web/js/whiteboard/calendar.jsrenderMonthView(calendar.js:234), clampcellHto a minimum of about14px (the 11 px font size + breathing room) so a programmaticbg.heightset — through persisted state loaded from the server, a legacy board, or any code path that bypassesapplyTransform— cannot reintroduce the overlapping-rows bug seen in the attached video.hourHinrenderWeekViewandrenderDayView(Math.max(10, ...)), so time rows can't collapse either.Dependencies: none.
Acceptance Criteria
boundBoxFuncin the transformer is not triggered to abort the drag.Math.max(14, …)floor engaged (no overlapping text).Notes
keepRatio: trueoverride? Because the reported bug is that users want the calendar to take different aspect ratios — it is the preview during drag that misleads, not the final shape. Live redraw keeps the existing free-resize flexibility.transformevent fires very frequently. The calendarredrawrebuilds a few dozen Konva nodes; on modern hardware this is <1 ms and comfortably 60 Hz-capable. If profiling shows it stuttering on low-end hardware, add a simple rAF throttle inside the handler.Test Results
cargo check --workspace: passcargo clippy -- -D warnings: passcargo fmt --check: passcargo test --workspace --lib: 0 passed / 0 failed (0)Note: changes are entirely in vanilla JS (frontend); UI behavior must be verified manually in the browser.
Implementation Summary
All three steps from the approved spec are implemented.
Changes
crates/hero_whiteboard_ui/static/web/js/whiteboard/calendar.jsgetMinSize(viewMode)returning per-view minimums: month 280x260, week 320x220, day 200x280 (default 240x200). Exported from the module.cellH = Math.max(14, (contentH - 20) / 6)in the month view;hourH = Math.max(10, ...)in the week and day views.crates/hero_whiteboard_ui/static/web/js/whiteboard/objects.jsapplyTransformcalendar branch now clamps to the view-aware minimum returned byWhiteboardCalendar.getMinSize(node._calState.viewMode)instead of the hardcoded 240x200.crates/hero_whiteboard_ui/static/web/js/whiteboard/tools.jstransformer.on('transform', ...)handler that fires continuously during a resize drag. For calendar nodes it applies the current scale to the bg, clamps to the view-aware minimum, resets the group scale to 1, and callsWhiteboardCalendar.redraw(node)so children re-lay-out on every tick.transformer.forceUpdate()after so the outline hugs the clamped box. Scoped to calendars only; other object types are unaffected.Test Results
cargo check --workspace: passcargo clippy --workspace -- -D warnings: passcargo fmt --check: passcargo test --workspace --lib: 0 passed / 0 failed (no lib tests in the workspace)Changes are entirely vanilla JS (frontend). UI behavior needs manual verification in the browser.
Manual verification checklist
Pull request opened: #24
This PR implements the changes discussed in this issue.