sky.html: snap-binary aperture scroll (wheel ↔ form, full aperture each); SAVE SKY animates scrollTop back to 0 — TDD
post-save the .sky-page aperture flips into scroll-snap-y-mandatory mode: wheel-col & form-col each fill the aperture & carry scroll-snap-align:start, so vertical scroll toggles between them rather than free-flowing through both. Modal-body uses display:contents so the cols become direct flex children of .sky-page (where min-height:100% resolves against the explicit aperture height); wheel-col's aspect-ratio/max-height caps are released under body.sky-saved so the section actually fills the aperture instead of clipping at 480px. SAVE SKY's success branch calls _scrollApertureToTop(), a 280ms RAF loop w. ease-out cubic so the user lands back on the wheel after confirming from the form section. New FT class MySkyApertureSnapScrollTest covers (T1) snap-type:y mandatory + scroll-snap-align:start on both cols, (T2) scrollTop returns to 0 after SAVE SKY click; both red before the SCSS+JS, green after. Snap behavior is gated on body.sky-saved (set by sky_view based on user.sky_chart_data) so the pre-save form-only flow is untouched. Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -304,13 +304,40 @@
|
||||
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
||||
return r.json();
|
||||
})
|
||||
.then(data => { setStatus('Sky saved!'); Note.handleSaveResponse(data); })
|
||||
.then(data => {
|
||||
setStatus('Sky saved!');
|
||||
Note.handleSaveResponse(data);
|
||||
_scrollApertureToTop();
|
||||
})
|
||||
.catch(err => {
|
||||
setStatus(`Save failed: ${err.message}`, 'error');
|
||||
confirmBtn.disabled = false;
|
||||
});
|
||||
});
|
||||
|
||||
// ── Snap-back scroll on save ────────────────────────────────────────────
|
||||
// .sky-page is scroll-snap-y-mandatory (post-save). After SAVE SKY the user
|
||||
// should land back on the wheel section even if they clicked from the form
|
||||
// section. cubic-bezier(0.2, 0.9, 0.4, 1) — fast start, gentle settle.
|
||||
|
||||
function _scrollApertureToTop() {
|
||||
if (overlay.scrollTop === 0) return;
|
||||
const start = overlay.scrollTop;
|
||||
const startTime = performance.now();
|
||||
const DURATION = 280;
|
||||
const ease = (t) => {
|
||||
// ease-out cubic — visually equivalent to cubic-bezier(0, 0, 0.4, 1).
|
||||
const u = 1 - t;
|
||||
return 1 - u * u * u;
|
||||
};
|
||||
function step(now) {
|
||||
const t = Math.min(1, (now - startTime) / DURATION);
|
||||
overlay.scrollTop = Math.max(0, start * (1 - ease(t)));
|
||||
if (t < 1) requestAnimationFrame(step);
|
||||
}
|
||||
requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
// ── CSRF ─────────────────────────────────────────────────────────────────
|
||||
|
||||
function _getCsrf() {
|
||||
|
||||
Reference in New Issue
Block a user