From 9dc896964d9f6595d11d2a6e81e83348a425e5d0 Mon Sep 17 00:00:00 2001 From: Ramon Date: Thu, 23 Jul 2026 19:05:53 +0200 Subject: [PATCH] fix: maak mobiele opdrachten volledig zichtbaar --- VERSION | 2 +- public/css/teach.css | 20 +++++++++++++++++++- public/js/core.js | 15 ++++++++++++++- test/frontend.test.js | 14 ++++++++++++-- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/VERSION b/VERSION index 3e4db6e..4f42abb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.53-beta +0.4.54-beta diff --git a/public/css/teach.css b/public/css/teach.css index 3099d3d..4c67de5 100644 --- a/public/css/teach.css +++ b/public/css/teach.css @@ -47,7 +47,10 @@ daadwerkelijk zichtbare hoogte wanneer de browserbalk in- of uitschuift. Doordat body een containing block is, gebruiken ook de absoluut gepositioneerde bord-, leerling- en ouderweergaven deze zichtbare hoogte. */ - html,body{height:100%; height:100dvh; margin:0; overflow:hidden;} + html,body{ + height:100%; height:100dvh; height:var(--app-height,100dvh); + margin:0; overflow:hidden; + } body{ position:relative; font-family:"Quicksand","Segoe UI Rounded","Arial Rounded MT Bold",ui-rounded,"Segoe UI",Verdana,sans-serif; @@ -2057,6 +2060,21 @@ body.dark .world-fact{background:#1d3b2a;color:#a9e5b7}body.dark .world-fact .wo overscroll-behavior:contain; } #pupilView .pupil-card{width:100%!important;max-width:100%;min-width:0!important} + /* Op een laag telefoonscherm wordt een bordwidget begrensd tot het zichtbare + bord. De inhoud moet dan kunnen scrollen; overflow:hidden sneed vooral de + opdrachtkaart en blokkenbak af. Letter/rekenroots mogen daarbij hoger + worden dan hun viewport, waarna widget-body de scroll afhandelt. */ + .widget-body{ + overflow-y:auto; + overscroll-behavior:contain; + -webkit-overflow-scrolling:touch; + } + .widget-body>:is(.lg,.mt){flex:none;min-height:100%} + .lg-card{min-height:210px} + .mt-card{min-height:180px} + /* De knop is buiten een opgelost woord display:none. De oude vaste 46px + liet desondanks een lege witte "footer" onder de blokken staan. */ + .lg-bottom{min-height:0} .widget:not(.bare){max-width:calc(100% - 8px)} .widget-head{gap:4px;padding:6px 8px} .widget-head .wicon{font-size:18px} diff --git a/public/js/core.js b/public/js/core.js index 4c1d6e0..9536e81 100644 --- a/public/js/core.js +++ b/public/js/core.js @@ -2,7 +2,20 @@ "use strict"; /* version — shown until /api/version resolves (or if the fetch fails, e.g. offline). Kept in sync by hand with the VERSION file at the repo root on every release. */ -const VERSION = "0.4.53-beta"; +const VERSION = "0.4.54-beta"; +/* Safari en oudere mobiele browsers behandelen 100vh/100% soms als de hoogte + achter hun adres- en navigatiebalk. visualViewport geeft de werkelijk + zichtbare hoogte; de CSS gebruikt deze pixelwaarde als betrouwbare bron en + blijft via resize ook bij draaien en in-/uitschuiven van browserbalken bij. */ +(function trackVisibleViewport(){ + const update=()=>{ + const height=window.visualViewport?.height || window.innerHeight; + if(height>0)document.documentElement.style.setProperty("--app-height",Math.round(height)+"px"); + }; + update(); + window.addEventListener("resize",update,{passive:true}); + window.visualViewport?.addEventListener("resize",update,{passive:true}); +})(); (function(){ const tag = document.getElementById("verTag"); tag.textContent = "v"+VERSION; diff --git a/test/frontend.test.js b/test/frontend.test.js index 32124a8..eecb012 100644 --- a/test/frontend.test.js +++ b/test/frontend.test.js @@ -109,9 +109,19 @@ test('index.html: elk script heeft defer + cache-busting, font-preload blijft on }); test('mobiele leerlingweergave volgt de zichtbare viewport zonder witte onderstrook', async () => { - const css = await readFile(join(publicRoot, 'css', 'teach.css'), 'utf8'); - assert.match(css, /html,body\{height:100%; height:100dvh;/); + const [css, core] = await Promise.all([ + readFile(join(publicRoot, 'css', 'teach.css'), 'utf8'), + readFile(join(publicRoot, 'js', 'core.js'), 'utf8'), + ]); + assert.match(css, /height:var\(--app-height,100dvh\)/); assert.match(css, /body\{\s*position:relative;/); + assert.match(core, /window\.visualViewport\?\.height \|\| window\.innerHeight/); + assert.match(core, /visualViewport\?\.addEventListener\("resize",update/); const phone = css.slice(css.indexOf('Widgetinhoud op telefoonformaat')); assert.match(phone, /body\.pupil-mode #pupilView\{[^}]*safe-area-inset-bottom[^}]*overscroll-behavior:contain;/); + assert.match(phone, /\.widget-body\{[^}]*overflow-y:auto[^}]*-webkit-overflow-scrolling:touch;/); + assert.match(phone, /\.widget-body>:is\(\.lg,\.mt\)\{flex:none;min-height:100%\}/); + assert.match(phone, /\.lg-card\{min-height:210px\}/); + assert.match(phone, /\.mt-card\{min-height:180px\}/); + assert.match(phone, /\.lg-bottom\{min-height:0\}/); });