From 8023ecfb343d0bfe2ae40b8a7734d8db93d70cb3 Mon Sep 17 00:00:00 2001 From: Dan Walker Date: Sun, 31 May 2026 08:08:16 -0700 Subject: [PATCH 1/4] Move slide thumbnails into responsive side rail --- propresenter_notes/static/style.css | 62 ++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/propresenter_notes/static/style.css b/propresenter_notes/static/style.css index 06f4538..0070b92 100644 --- a/propresenter_notes/static/style.css +++ b/propresenter_notes/static/style.css @@ -18,7 +18,7 @@ body { button, select, input { font: inherit; } .app { - width: min(1100px, calc(100% - (var(--page-gutter) * 2))); + width: min(1280px, calc(100% - (var(--page-gutter) * 2))); margin: 24px auto; display: grid; gap: 16px; @@ -209,6 +209,66 @@ input { color: #fca5a5; } +@media (min-width: 901px) { + .app { + --thumbnail-sidebar-width: clamp(212px, 22vw, 300px); + grid-template-columns: var(--thumbnail-sidebar-width) minmax(0, 1fr); + align-items: start; + } + + .topbar, + .controls { + grid-column: 1 / -1; + } + + .slideBrowser { + position: sticky; + top: 16px; + align-self: start; + max-height: calc(100dvh - 32px); + display: flex; + flex-direction: column; + } + + .slideBrowser .meta { + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: 6px; + } + + #cacheStatus { + text-align: left; + } + + .thumbnailStrip { + --thumbnail-min: 0; + grid-template-columns: minmax(0, 1fr); + flex: 1; + max-height: none; + min-height: 0; + } + + .now, + .debug { + grid-column: 2; + } +} + +@media (min-width: 901px) and (max-height: 680px) { + .app { + margin-block: 16px; + } + + .panel { + padding: 16px; + } + + .slideBrowser { + top: 12px; + max-height: calc(100dvh - 24px); + } +} + @media (max-width: 700px) { :root { --page-gutter: 10px; From 923afec839d2a7ad125bdff933b2f67956170437 Mon Sep 17 00:00:00 2001 From: Dan Walker Date: Sun, 31 May 2026 08:14:14 -0700 Subject: [PATCH 2/4] Make sidebar thumbnails resize responsively --- propresenter_notes/static/style.css | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/propresenter_notes/static/style.css b/propresenter_notes/static/style.css index 0070b92..579a54a 100644 --- a/propresenter_notes/static/style.css +++ b/propresenter_notes/static/style.css @@ -211,7 +211,7 @@ input { @media (min-width: 901px) { .app { - --thumbnail-sidebar-width: clamp(212px, 22vw, 300px); + --thumbnail-sidebar-width: clamp(176px, 20vw, 360px); grid-template-columns: var(--thumbnail-sidebar-width) minmax(0, 1fr); align-items: start; } @@ -241,8 +241,9 @@ input { } .thumbnailStrip { - --thumbnail-min: 0; - grid-template-columns: minmax(0, 1fr); + --thumbnail-min: clamp(112px, 10vw, 164px); + grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--thumbnail-min)), 1fr)); + align-content: start; flex: 1; max-height: none; min-height: 0; @@ -254,6 +255,12 @@ input { } } +@media (min-width: 1200px) { + .app { + --thumbnail-sidebar-width: clamp(300px, 26vw, 420px); + } +} + @media (min-width: 901px) and (max-height: 680px) { .app { margin-block: 16px; From 3aed3ec5352cf3aa32d9e4ae3135d7aca897bf32 Mon Sep 17 00:00:00 2001 From: Dan Walker Date: Sun, 31 May 2026 08:20:24 -0700 Subject: [PATCH 3/4] Prevent iPad thumbnail overlap --- propresenter_notes/static/style.css | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/propresenter_notes/static/style.css b/propresenter_notes/static/style.css index 579a54a..b1cf02c 100644 --- a/propresenter_notes/static/style.css +++ b/propresenter_notes/static/style.css @@ -119,7 +119,9 @@ h2 { --thumbnail-min: clamp(104px, 16vw, 168px); display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--thumbnail-min)), 1fr)); - gap: 12px; + gap: var(--thumbnail-gap, 12px); + grid-auto-rows: max-content; + align-items: start; max-height: min(42vh, 360px); overflow-x: hidden; overflow-y: auto; @@ -130,8 +132,9 @@ h2 { } .thumbnailCard { - display: block; + display: grid; min-width: 0; + width: 100%; padding: 6px; border-radius: 16px; background: #020617; @@ -153,6 +156,8 @@ h2 { width: 100%; aspect-ratio: 16 / 9; border-radius: 10px; + display: block; + min-width: 0; object-fit: cover; background: #1e293b; } @@ -241,8 +246,8 @@ input { } .thumbnailStrip { - --thumbnail-min: clamp(112px, 10vw, 164px); - grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--thumbnail-min)), 1fr)); + --thumbnail-gap: clamp(10px, 1.2vw, 16px); + grid-template-columns: minmax(0, 1fr); align-content: start; flex: 1; max-height: none; @@ -261,6 +266,13 @@ input { } } +@media (min-width: 1400px) and (hover: hover) and (pointer: fine) { + .thumbnailStrip { + --thumbnail-min: clamp(132px, 10vw, 180px); + grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--thumbnail-min)), 1fr)); + } +} + @media (min-width: 901px) and (max-height: 680px) { .app { margin-block: 16px; From e5bd9261534116d0c7596ce59fa1e6f9c39a56d7 Mon Sep 17 00:00:00 2001 From: Dan Walker Date: Sun, 31 May 2026 08:25:18 -0700 Subject: [PATCH 4/4] Pin navigation controls and gate debug output --- propresenter_notes/static/app.js | 5 ++++ propresenter_notes/static/style.css | 39 +++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/propresenter_notes/static/app.js b/propresenter_notes/static/app.js index 23f2344..623d0b0 100644 --- a/propresenter_notes/static/app.js +++ b/propresenter_notes/static/app.js @@ -27,6 +27,11 @@ const selectionStorageKey = 'propresenter-notes-selection'; const presentationsStorageKey = 'propresenter-notes-presentations'; const presentationCacheStoragePrefix = 'propresenter-notes-cache:'; +const debugEnabled = ['1', 'true', 'yes'].includes( + new URLSearchParams(window.location.search).get('debug')?.toLowerCase() || '' +); +document.body.classList.toggle('debugEnabled', debugEnabled); + function readStoredSelection() { try { return JSON.parse(window.localStorage.getItem(selectionStorageKey) || '{}'); diff --git a/propresenter_notes/static/style.css b/propresenter_notes/static/style.css index b1cf02c..138da4f 100644 --- a/propresenter_notes/static/style.css +++ b/propresenter_notes/static/style.css @@ -5,6 +5,7 @@ color: #f9fafb; --page-gutter: clamp(12px, 4vw, 32px); --touch-target: 48px; + --nav-dock-height: 92px; } * { box-sizing: border-box; } @@ -20,6 +21,7 @@ button, select, input { font: inherit; } .app { width: min(1280px, calc(100% - (var(--page-gutter) * 2))); margin: 24px auto; + padding-bottom: calc(var(--nav-dock-height) + env(safe-area-inset-bottom)); display: grid; gap: 16px; } @@ -66,6 +68,24 @@ button:hover { background: #1e293b; } button:disabled { opacity: .55; cursor: not-allowed; } .primary { background: #2563eb; border-color: #60a5fa; } .primary:hover { background: #1d4ed8; } +.buttonRow { + position: fixed; + left: 50%; + bottom: calc(16px + env(safe-area-inset-bottom)); + z-index: 30; + display: grid; + grid-template-columns: repeat(2, minmax(130px, 1fr)); + gap: 10px; + width: min(420px, calc(100% - (var(--page-gutter) * 2))); + padding: 10px; + border: 1px solid rgba(255,255,255,0.12); + border-radius: 22px; + background: rgba(3, 7, 18, 0.82); + box-shadow: 0 16px 44px rgba(0,0,0,0.38); + backdrop-filter: blur(14px); + transform: translateX(-50%); +} + .navButton { min-width: 150px; font-weight: 700; } .now { min-height: 420px; display: flex; flex-direction: column; } @@ -80,6 +100,8 @@ button:disabled { opacity: .55; cursor: not-allowed; } margin: 24px 0 0; touch-action: pan-y; } +.debug { display: none; } +body.debugEnabled .debug { display: block; } .debug pre { white-space: pre-wrap; overflow-x: auto; color: #cbd5e1; } .statusGood { color: #86efac; } @@ -309,7 +331,7 @@ input { min-height: 100dvh; margin: 0; gap: 10px; - padding: 10px 10px calc(116px + env(safe-area-inset-bottom)); + padding: 10px 10px calc(var(--nav-dock-height) + 20px + env(safe-area-inset-bottom)); } .panel { @@ -369,19 +391,18 @@ input { } .buttonRow { - position: fixed; left: 0; right: 0; bottom: 0; - z-index: 20; - display: grid; + z-index: 30; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); - gap: 10px; + width: auto; padding: 12px 10px calc(12px + env(safe-area-inset-bottom)); + border-width: 1px 0 0; + border-radius: 0; background: rgba(3, 7, 18, 0.94); - border-top: 1px solid rgba(255,255,255,0.12); box-shadow: 0 -12px 36px rgba(0,0,0,0.38); - backdrop-filter: blur(14px); + transform: none; } .navButton { @@ -427,6 +448,10 @@ input { display: none; } + body.debugEnabled .debug { + display: block; + } + .loginApp { align-items: start; padding: 16px;