From 531c2295bd254e6a47770693418c186acd729a98 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Sun, 6 Jul 2025 18:14:42 +0200 Subject: [PATCH] Added header/footer animation --- app/static/css/default.css | 20 +++++++++++ app/static/js/fullscreen.js | 68 ++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 32 deletions(-) diff --git a/app/static/css/default.css b/app/static/css/default.css index c07b770..db5e677 100644 --- a/app/static/css/default.css +++ b/app/static/css/default.css @@ -156,4 +156,24 @@ iframe{ /* start invisible but in the layout (d-none will actually hide it) */ opacity: 0; transition: opacity var(--anim-duration) ease-in-out; +} + +/* 1. Make sure headers and footers can collapse */ +header, +footer { + overflow: hidden; + /* choose a max-height that’s >= your tallest header/footer */ + max-height: 200px; + padding: 1rem; + transition: + max-height var(--anim-duration) ease-in-out, + padding var(--anim-duration) ease-in-out; +} + +/* 2. In fullscreen mode, collapse them */ +body.fullscreen header, +body.fullscreen footer { + max-height: 0; + padding-top: 0; + padding-bottom: 0; } \ No newline at end of file diff --git a/app/static/js/fullscreen.js b/app/static/js/fullscreen.js index 4dc6cca..3df9a08 100644 --- a/app/static/js/fullscreen.js +++ b/app/static/js/fullscreen.js @@ -10,47 +10,58 @@ function updateUrlFullscreen(enabled) { } /** - * Enter fullscreen: hide header/footer, enable full width, recalc scroll, - * set both URL params, update button. + * Starts a requestAnimationFrame loop that calls your recalc methods, + * and stops automatically when the header’s max-height transition ends. */ -function enterFullscreen() { - // hide header/footer - document.querySelectorAll('header, footer').forEach(el => el.style.display = 'none'); +function recalcWhileCollapsing() { + const header = document.querySelector('header'); + if (!header) return; - // go full-width + // 1) Start the RAF loop + let rafId; + const step = () => { + adjustScrollContainerHeight(); + updateCustomScrollbar(); + rafId = requestAnimationFrame(step); + }; + step(); + + // 2) Listen for the end of the max-height transition + function onEnd(e) { + if (e.propertyName === 'max-height') { + cancelAnimationFrame(rafId); + header.removeEventListener('transitionend', onEnd); + } + } + header.addEventListener('transitionend', onEnd); +} + +function enterFullscreen() { + document.body.classList.add('fullscreen'); setFullWidth(true); updateUrlFullscreen(true); - // fade in logo + // fade in logo… (unchanged) const logo = document.getElementById('navbar_logo'); if (logo) { logo.classList.remove('d-none'); - // next frame → trigger transition - requestAnimationFrame(() => { - logo.style.opacity = '1'; - }); + requestAnimationFrame(() => logo.style.opacity = '1'); } - // recalc scrollbars - if (typeof adjustScrollContainerHeight === 'function') adjustScrollContainerHeight(); - if (typeof updateCustomScrollbar === 'function') updateCustomScrollbar(); + // now recalc in lock-step with the CSS collapse animation + recalcWhileCollapsing(); } - -/** - * Exit fullscreen: show header/footer, disable full width, recalc scroll, - * clear both URL params, update button. - */ function exitFullscreen() { - // show header/footer - document.querySelectorAll('header, footer').forEach(el => el.style.display = ''); + document.body.classList.remove('fullscreen'); + setFullWidth(false); + updateUrlFullscreen(false); - // fade out logo + // fade out logo… (unchanged) const logo = document.getElementById('navbar_logo'); if (logo) { logo.style.opacity = '0'; logo.addEventListener('transitionend', function handler(e) { - // only once, and only for opacity if (e.propertyName === 'opacity') { logo.classList.add('d-none'); logo.removeEventListener('transitionend', handler); @@ -58,17 +69,10 @@ function exitFullscreen() { }); } - // reset width - setFullWidth(false); - updateUrlFullscreen(false); - - // recalc scrollbars - if (typeof adjustScrollContainerHeight === 'function') adjustScrollContainerHeight(); - if (typeof updateCustomScrollbar === 'function') updateCustomScrollbar(); - if (typeof syncIframeHeight === 'function') syncIframeHeight(); + // recalc while header/footer expand back + recalcWhileCollapsing(); } - /** * Toggle between enter and exit fullscreen. */