fix(rcal): consistent viewport sizing + touch pinch-zoom fix

Make calendar views fill a consistent ~60vh area across all zoom levels
(month/season/year/multi-year) using flex stretching. Fix touch pinch-zoom
by removing pinch-zoom from touch-action so our pointer handler fires
instead of native page zoom.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-31 18:26:52 -07:00
parent 1ad721a579
commit 1ee14b7520
1 changed files with 18 additions and 16 deletions

View File

@ -2756,7 +2756,7 @@ class FolkCalendarView extends HTMLElement {
/* ── Main Layout ── */
.main-layout { position: relative; min-height: 400px; }
.main-layout--docked { display: grid; grid-template-columns: 1fr 6px 400px; gap: 0; min-height: 500px; }
.calendar-pane { overflow: auto; min-width: 0; touch-action: pan-y pinch-zoom; user-select: none; }
.calendar-pane { overflow: auto; min-width: 0; touch-action: pan-y; user-select: none; min-height: 60vh; display: flex; flex-direction: column; }
/* ── Resize Handle ── */
.resize-handle { width: 6px; cursor: col-resize; background: transparent; position: relative; z-index: 10; transition: background 0.15s; }
@ -2787,8 +2787,8 @@ class FolkCalendarView extends HTMLElement {
/* ── Month Grid ── */
.weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 4px; }
.wd { text-align: center; font-size: 11px; color: var(--rs-text-muted); padding: 4px; font-weight: 600; }
.grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; position: relative; }
.day { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 6px; min-height: 80px; padding: 6px; cursor: pointer; position: relative; -webkit-tap-highlight-color: transparent; }
.grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; position: relative; flex: 1; }
.day { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 6px; min-height: 0; padding: 6px; cursor: pointer; position: relative; -webkit-tap-highlight-color: transparent; }
.day:hover { border-color: var(--rs-border-strong); }
.day.today { border-color: var(--rs-primary-hover); background: var(--rs-bg-active); }
.day.expanded { border-color: var(--rs-primary-hover); background: rgba(99,102,241,0.1); }
@ -2908,11 +2908,11 @@ class FolkCalendarView extends HTMLElement {
.modal-close { float: right; background: none; border: none; color: var(--rs-text-muted); font-size: 18px; cursor: pointer; }
/* ── Day View ── */
.day-view { position: relative; }
.day-view { position: relative; flex: 1; display: flex; flex-direction: column; }
.day-view-header { font-size: 13px; color: var(--rs-text-secondary); margin-bottom: 8px; font-weight: 500; }
.day-allday { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 8px; padding: 8px; margin-bottom: 8px; }
.day-allday-label { font-size: 10px; color: var(--rs-text-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 4px; }
.timeline { position: relative; border-left: 1px solid var(--rs-border); margin-left: 44px; }
.timeline { position: relative; border-left: 1px solid var(--rs-border); margin-left: 44px; flex: 1; }
.hour-row { display: flex; min-height: 48px; border-bottom: 1px solid var(--rs-border-subtle); position: relative; }
.hour-label { position: absolute; left: -48px; top: -7px; width: 40px; text-align: right; font-size: 10px; color: var(--rs-text-muted); font-variant-numeric: tabular-nums; }
.hour-content { flex: 1; position: relative; padding-left: 8px; }
@ -2928,14 +2928,14 @@ class FolkCalendarView extends HTMLElement {
.now-dot { position: absolute; left: -5px; top: -3px; width: 8px; height: 8px; border-radius: 50%; background: var(--rs-error); }
/* ── Week View ── */
.week-view { overflow-x: auto; }
.week-view { overflow-x: auto; flex: 1; display: flex; flex-direction: column; }
.week-header { display: grid; grid-template-columns: 44px repeat(7, 1fr); gap: 0; margin-bottom: 0; }
.week-day-header { text-align: center; padding: 8px 4px; font-size: 11px; color: var(--rs-text-muted); font-weight: 600; border-bottom: 1px solid var(--rs-border); cursor: pointer; }
.week-day-header:hover { color: var(--rs-text-primary); }
.week-day-header.today { color: var(--rs-primary-hover); border-bottom-color: var(--rs-primary-hover); }
.week-day-num { font-size: 16px; font-weight: 700; display: block; }
.week-day-name { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; }
.week-grid { display: grid; grid-template-columns: 44px repeat(7, 1fr); }
.week-grid { display: grid; grid-template-columns: 44px repeat(7, 1fr); flex: 1; }
.week-time-label { font-size: 10px; color: var(--rs-text-muted); text-align: right; padding-right: 6px; font-variant-numeric: tabular-nums; height: 48px; }
.week-cell { border-left: 1px solid var(--rs-border-subtle); border-bottom: 1px solid var(--rs-border-subtle); min-height: 48px; position: relative; }
.week-cell.today { background: rgba(99,102,241,0.04); }
@ -2950,22 +2950,22 @@ class FolkCalendarView extends HTMLElement {
/* ── Season View ── */
.season-header { text-align: center; margin-bottom: 12px; font-size: 16px; font-weight: 600; color: var(--rs-text-primary); }
.season-q { font-size: 12px; color: var(--rs-text-muted); font-weight: 400; margin-left: 4px; }
.season-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.season-month-wrap { display: flex; flex-direction: column; gap: 4px; }
.season-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; flex: 1; align-content: stretch; }
.season-month-wrap { display: flex; flex-direction: column; gap: 4px; flex: 1; }
.season-cities { display: flex; flex-wrap: wrap; gap: 3px; padding: 2px 4px; }
.season-city-chip { font-size: 9px; color: var(--rs-text-secondary); background: var(--rs-bg-hover); border: 1px solid var(--rs-border-strong); border-radius: 8px; padding: 1px 6px; white-space: nowrap; }
/* ── Year View ── */
.year-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.year-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; flex: 1; align-content: stretch; }
/* ── Mini-Month (shared) ── */
.mini-month { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 8px; padding: 8px; cursor: pointer; transition: border-color 0.15s; }
.mini-month { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 8px; padding: 8px; cursor: pointer; transition: border-color 0.15s; flex: 1; display: flex; flex-direction: column; }
.mini-month:hover { border-color: var(--rs-border-strong); }
.mini-month.current { border-color: var(--rs-primary-hover); background: var(--rs-bg-active); }
.mini-month-title { font-size: 12px; font-weight: 600; text-align: center; color: var(--rs-text-primary); margin-bottom: 4px; }
.mini-wd-row { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; margin-bottom: 2px; }
.mini-wd { text-align: center; font-size: 8px; color: var(--rs-text-muted); font-weight: 600; }
.mini-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; }
.mini-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; flex: 1; align-content: start; }
.mini-day { position: relative; display: flex; align-items: center; justify-content: center; font-size: 10px; color: var(--rs-text-secondary); border-radius: 3px; aspect-ratio: 1; cursor: pointer; }
.mini-day:hover { background: var(--rs-bg-hover); }
.mini-day.today { background: var(--rs-primary); color: #fff; font-weight: 700; }
@ -3053,7 +3053,7 @@ class FolkCalendarView extends HTMLElement {
.yv-country { font-size: 9px; color: var(--rs-text-muted); margin-left: 6px; font-weight: 400; }
/* ── Multi-Year View ── */
.multi-year-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.multi-year-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; flex: 1; align-content: stretch; }
.my-year { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 8px; padding: 8px; cursor: pointer; transition: border-color 0.15s; }
.my-year:hover { border-color: var(--rs-border-strong); }
.my-year.current { border-color: var(--rs-primary-hover); background: var(--rs-bg-active); }
@ -3078,17 +3078,18 @@ class FolkCalendarView extends HTMLElement {
.main-layout--docked { grid-template-columns: 1fr !important; }
.resize-handle { display: none; }
.ev-label { display: none; }
.day { min-height: 64px; }
.day { min-height: 0; }
.zoom-bar--top .zoom-bar__track { min-width: 140px; }
}
/* ── Mobile ── */
@media (max-width: 768px) {
:host { padding: 0.25rem; }
.calendar-pane { min-height: 50vh; }
.main-layout--docked { grid-template-columns: 1fr !important; }
.resize-handle { display: none; }
.year-grid { grid-template-columns: repeat(3, 1fr); }
.season-grid { grid-template-columns: 1fr; }
.day { min-height: 48px; padding: 4px; }
.day { min-height: 0; padding: 4px; }
.day-num { font-size: 11px; }
.ev-label { display: none; }
/* Dots → thin colored bars on mobile */
@ -3123,7 +3124,8 @@ class FolkCalendarView extends HTMLElement {
.mt-day-name { width: 30px; font-size: 10px; }
}
@media (max-width: 480px) {
.day { min-height: 40px; padding: 3px; }
.calendar-pane { min-height: 45vh; }
.day { min-height: 0; padding: 3px; }
.day-num { font-size: 10px; }
.dot { height: 1.5px; }
.dot--tentative { border-top-width: 1.5px; }