From a0d492c702268a4de1ce5b19342c330abe7706cb Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Wed, 24 Dec 2025 12:57:59 +0100 Subject: [PATCH 01/35] New 10-foot display option Can be used to view long lyrics among other things in a large gathering --- components/base_layout_10foot.pug | 47 +++++++ pages/10foot.pug | 28 ++++ scripts/tenfoot-navigation.js | 114 ++++++++++++++++ styles/tenfoot.scss | 213 ++++++++++++++++++++++++++++++ 4 files changed, 402 insertions(+) create mode 100644 components/base_layout_10foot.pug create mode 100644 pages/10foot.pug create mode 100644 scripts/tenfoot-navigation.js create mode 100644 styles/tenfoot.scss diff --git a/components/base_layout_10foot.pug b/components/base_layout_10foot.pug new file mode 100644 index 0000000..f695d5f --- /dev/null +++ b/components/base_layout_10foot.pug @@ -0,0 +1,47 @@ +include core + +block pug_meta + +- const title = typeof page_title === 'string' ? `${page_title} - ${app_name}` : app_name; + +doctype html +html(lang="en") + +head(title) + link(rel="stylesheet" href="/styles/tenfoot.scss") + body + main + +vspace("25px") + img.big-logo(src="/media/flogo.svg" height="200") + +vspace("25px") + header + block title + + if show_load_indicator + #loading-indicator.spinner + img(width="200" src="/media/fstjerne.svg") + + header.header-with-logo + .logo-title-container + .logo-wrapper + img.logo(src="/media/fstjerne.svg" alt="Logo") + .title-wrapper + h1= app_name || 'Welcome' + .subtitle Select a service to continue + + cast-media-player + block content + if hide_frit_fit !== true + p.frit-fit #fritfit (for real) + + .nav-hint + span Navigate with + kbd ↑ + kbd ↓ + kbd ← + kbd → + kbd Enter + + +scripts + script(type="module" src="/scripts/tenfoot-navigation.js") + script(type="module" src="/scripts/chromecast-receiver.js") + block scripts \ No newline at end of file diff --git a/pages/10foot.pug b/pages/10foot.pug new file mode 100644 index 0000000..3ff92f5 --- /dev/null +++ b/pages/10foot.pug @@ -0,0 +1,28 @@ +extends ../components/base_layout_10foot + +block title + h1 Welcome + .subtitle Select a service to continue + +block content + +vspace("25px") + section.service-links.border-outer + a.service-card(tabindex="0" role="button" href=navigation[key]) + .service-icon 📺 + .service-title Live TV + .service-description Watch live channels and broadcasts + + .service-card(tabindex="1" role="button" data-service="movies") + .service-icon 🎬 + .service-title Movies + .service-description Browse our collection of films + + .service-card(tabindex="2" role="button" data-service="tvshows") + .service-icon 📺 + .service-title TV Shows + .service-description Stream your favorite series + + .service-card(tabindex="3" role="button" data-service="settings") + .service-icon ⚙️ + .service-title Settings + .service-description Customize your experience diff --git a/scripts/tenfoot-navigation.js b/scripts/tenfoot-navigation.js new file mode 100644 index 0000000..1268f3d --- /dev/null +++ b/scripts/tenfoot-navigation.js @@ -0,0 +1,114 @@ +// ten-foot-navigation.js +// Keyboard navigation for 10-foot interface + +class TenFootNavigator { + constructor() { + this.cards = document.querySelectorAll('.service-card'); + this.currentIndex = 0; + this.init(); + } + + init() { + this.setupKeyboardNavigation(); + this.setupClickHandlers(); + this.handleLoading(); + + // Focus first card on load + if (this.cards.length > 0) { + this.focusCard(0); + } + } + + focusCard(index) { + if (index >= 0 && index < this.cards.length) { + this.cards[index].focus(); + this.currentIndex = index; + } + } + + getColumns() { + return window.innerWidth > 1200 ? Math.min(3, this.cards.length) : 1; + } + + setupKeyboardNavigation() { + document.addEventListener('keydown', (e) => { + const cols = this.getColumns(); + + switch(e.key) { + case 'ArrowRight': + e.preventDefault(); + this.focusCard((this.currentIndex + 1) % this.cards.length); + break; + + case 'ArrowLeft': + e.preventDefault(); + this.focusCard((this.currentIndex - 1 + this.cards.length) % this.cards.length); + break; + + case 'ArrowDown': + e.preventDefault(); + this.focusCard(Math.min(this.currentIndex + cols, this.cards.length - 1)); + break; + + case 'ArrowUp': + e.preventDefault(); + this.focusCard(Math.max(this.currentIndex - cols, 0)); + break; + + case 'Enter': + e.preventDefault(); + this.cards[this.currentIndex].click(); + break; + } + }); + } + + setupClickHandlers() { + this.cards.forEach((card, index) => { + card.addEventListener('click', () => { + const service = card.dataset.service; + const title = card.querySelector('.service-title').textContent; + + console.log(`Selected: ${title} (${service})`); + + // Dispatch custom event for handling navigation + const event = new CustomEvent('serviceSelected', { + detail: { service, title, index } + }); + document.dispatchEvent(event); + + // Add your navigation logic here + // Example: window.location.href = `/service/${service}`; + }); + + // Track focus changes + card.addEventListener('focus', () => { + this.currentIndex = index; + }); + }); + } + + handleLoading() { + const loadingIndicator = document.getElementById('loading-indicator'); + + if (loadingIndicator) { + window.addEventListener('load', () => { + setTimeout(() => { + loadingIndicator.style.display = 'none'; + }, 1500); + }); + } + } +} + +// Initialize when DOM is ready +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + new TenFootNavigator(); + }); +} else { + new TenFootNavigator(); +} + +// Export for use in other modules if needed +export default TenFootNavigator; \ No newline at end of file diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss new file mode 100644 index 0000000..811d768 --- /dev/null +++ b/styles/tenfoot.scss @@ -0,0 +1,213 @@ +// ten-foot.scss +// Variables +$primary-gradient-start: #1a1a2e; +$primary-gradient-end: #16213e; +$text-color: #ffffff; +$card-bg: rgba(255, 255, 255, 0.1); +$card-bg-hover: rgba(255, 255, 255, 0.15); +$card-border: rgba(255, 255, 255, 0.2); +$card-border-hover: rgba(255, 255, 255, 0.4); +$focus-color: #00d4ff; + +// Mixins +@mixin card-shadow { + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4); +} + +@mixin text-shadow { + text-shadow: 0 4px 8px rgba(0, 0, 0, 0.5); +} + +@mixin smooth-transition($properties: all, $duration: 0.3s) { + transition: $properties $duration ease; +} + +// Reset +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +// Body +body { + background: linear-gradient(135deg, $primary-gradient-start 0%, $primary-gradient-end 100%); + color: $text-color; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + overflow-x: hidden; +} + +main { + min-height: 100vh; + display: flex; + flex-direction: column; + padding: 4rem; +} + +// Loading Indicator +#loading-indicator { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 1000; + + &.spinner { + animation: spin 2s linear infinite; + } + + img { + width: 200px; + height: 200px; + filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.5)); + } +} + +@keyframes spin { + 0% { + transform: translate(-50%, -50%) rotate(0deg); + } + 100% { + transform: translate(-50%, -50%) rotate(360deg); + } +} + +// Header +header { + margin-bottom: 4rem; + + h1 { + font-size: 5rem; + font-weight: 700; + margin-bottom: 1rem; + @include text-shadow; + } + + .subtitle { + font-size: 2.5rem; + opacity: 0.8; + font-weight: 300; + } +} + +// Service Grid +.service-links { + flex: 1; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); + gap: 3rem; + margin-bottom: 4rem; +} + +.service-card { + background: $card-bg; + backdrop-filter: blur(10px); + border-radius: 2rem; + padding: 3rem; + @include smooth-transition; + border: 2px solid $card-border; + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + + &:hover, + &:focus { + transform: scale(1.05); + background: $card-bg-hover; + border-color: $card-border-hover; + @include card-shadow; + } + + .service-icon { + font-size: 6rem; + margin-bottom: 2rem; + filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); + } + + .service-title { + font-size: 3rem; + font-weight: 600; + margin-bottom: 1.5rem; + } + + .service-description { + font-size: 1.8rem; + opacity: 0.9; + line-height: 1.6; + } +} + +// Cast Media Player +cast-media-player { + position: fixed; + bottom: 0; + left: 0; + right: 0; + height: 150px; + background: rgba(0, 0, 0, 0.9); + backdrop-filter: blur(20px); + display: none; + + &.active { + display: block; + } +} + +// Footer +.frit-fit { + text-align: center; + font-size: 2rem; + opacity: 0.6; + padding: 2rem; + margin-top: auto; +} + +// Focus indicators for accessibility +*:focus { + outline: 4px solid $focus-color; + outline-offset: 4px; +} + +// Navigation hint +.nav-hint { + position: fixed; + bottom: 2rem; + right: 2rem; + font-size: 1.5rem; + opacity: 0.5; + display: flex; + gap: 1rem; + align-items: center; + + kbd { + background: rgba(255, 255, 255, 0.2); + padding: 0.5rem 1rem; + border-radius: 0.5rem; + font-family: monospace; + font-size: 1.3rem; + } +} + +// Responsive adjustments +@media (max-width: 1200px) { + main { + padding: 2rem; + } + + header { + h1 { + font-size: 3.5rem; + } + + .subtitle { + font-size: 2rem; + } + } + + .service-links { + grid-template-columns: 1fr; + gap: 2rem; + } +} From 816366aaba16d94edc52c77ba917c5692e429924 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Wed, 24 Dec 2025 13:50:06 +0100 Subject: [PATCH 02/35] Rename, restructure and restyle page --- .pugrc.js | 3 +- ...out_10foot.pug => base_layout_tenfoot.pug} | 34 ++++---- media/flogo_w.svg | 77 +++++++++++++++++++ pages/10foot.pug | 28 ------- pages/tenfoot.pug | 33 ++++++++ styles/tenfoot.scss | 72 ++++++++++++----- 6 files changed, 177 insertions(+), 70 deletions(-) rename components/{base_layout_10foot.pug => base_layout_tenfoot.pug} (55%) create mode 100644 media/flogo_w.svg delete mode 100644 pages/10foot.pug create mode 100644 pages/tenfoot.pug diff --git a/.pugrc.js b/.pugrc.js index 7183759..3f4600a 100644 --- a/.pugrc.js +++ b/.pugrc.js @@ -10,7 +10,8 @@ module.exports = { Songbook: "/pages/songbook/index.pug", Events: "/pages/events.pug", Links: "/pages/links.pug", - Offline: "/pages/offline.pug" + Offline: "/pages/offline.pug", + TenFoot: "/pages/tenfoot.pug", }, links: { Slack: "https://fklubben.slack.com", diff --git a/components/base_layout_10foot.pug b/components/base_layout_tenfoot.pug similarity index 55% rename from components/base_layout_10foot.pug rename to components/base_layout_tenfoot.pug index f695d5f..358caa9 100644 --- a/components/base_layout_10foot.pug +++ b/components/base_layout_tenfoot.pug @@ -9,30 +9,20 @@ html(lang="en") +head(title) link(rel="stylesheet" href="/styles/tenfoot.scss") body - main - +vspace("25px") - img.big-logo(src="/media/flogo.svg" height="200") - +vspace("25px") - header - block title + header.header-with-logo + .logo-title-container + .logo-wrapper + //img.big-logo(src="/media/flogo.svg" height="200") + img.logo(src="/media/flogo_w.svg" alt="Logo") + .title-wrapper + h1= app_name + block title + main if show_load_indicator #loading-indicator.spinner img(width="200" src="/media/fstjerne.svg") - header.header-with-logo - .logo-title-container - .logo-wrapper - img.logo(src="/media/fstjerne.svg" alt="Logo") - .title-wrapper - h1= app_name || 'Welcome' - .subtitle Select a service to continue - - cast-media-player - block content - if hide_frit_fit !== true - p.frit-fit #fritfit (for real) - .nav-hint span Navigate with kbd ↑ @@ -40,8 +30,12 @@ html(lang="en") kbd ← kbd → kbd Enter + block content + + footer + if hide_frit_fit !== true + p.frit-fit #fritfit (for real) +scripts script(type="module" src="/scripts/tenfoot-navigation.js") - script(type="module" src="/scripts/chromecast-receiver.js") block scripts \ No newline at end of file diff --git a/media/flogo_w.svg b/media/flogo_w.svg new file mode 100644 index 0000000..4d54b7d --- /dev/null +++ b/media/flogo_w.svg @@ -0,0 +1,77 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pages/10foot.pug b/pages/10foot.pug deleted file mode 100644 index 3ff92f5..0000000 --- a/pages/10foot.pug +++ /dev/null @@ -1,28 +0,0 @@ -extends ../components/base_layout_10foot - -block title - h1 Welcome - .subtitle Select a service to continue - -block content - +vspace("25px") - section.service-links.border-outer - a.service-card(tabindex="0" role="button" href=navigation[key]) - .service-icon 📺 - .service-title Live TV - .service-description Watch live channels and broadcasts - - .service-card(tabindex="1" role="button" data-service="movies") - .service-icon 🎬 - .service-title Movies - .service-description Browse our collection of films - - .service-card(tabindex="2" role="button" data-service="tvshows") - .service-icon 📺 - .service-title TV Shows - .service-description Stream your favorite series - - .service-card(tabindex="3" role="button" data-service="settings") - .service-icon ⚙️ - .service-title Settings - .service-description Customize your experience diff --git a/pages/tenfoot.pug b/pages/tenfoot.pug new file mode 100644 index 0000000..ac16f44 --- /dev/null +++ b/pages/tenfoot.pug @@ -0,0 +1,33 @@ +extends ../components/base_layout_tenfoot + +block title + h2 Welcome + .subtitle Select a service to continue + +block content + +vspace("25px") + section.service-container + a.service-card(tabindex="0" role="button" href=navigation[key]) + .service-icon 💵 + .service-title Stregsystem + .service-description Browse our collection of wares + + .service-card(tabindex="1" role="button" data-service="movies") + .service-icon 🎼 + .service-title Songbook + .service-description Browse our collection of songs + + .service-card(tabindex="2" role="button" data-service="tvshows") + .service-icon 📅 + .service-title Events + .service-description Stream your favorite series + + .service-card(tabindex="2" role="button" data-service="tvshows") + .service-icon 🌐 + .service-title Links + .service-description See nice links + + .service-card(tabindex="3" role="button" data-service="settings") + .service-icon ➜] + .service-title Exit + .service-description Leave 10-foot display diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index 811d768..2a8cbcf 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -30,7 +30,7 @@ $focus-color: #00d4ff; } // Body -body { +html { background: linear-gradient(135deg, $primary-gradient-start 0%, $primary-gradient-end 100%); color: $text-color; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; @@ -38,12 +38,57 @@ body { } main { - min-height: 100vh; + max-height: 100vh; display: flex; - flex-direction: column; + flex-direction: row; padding: 4rem; } +// Header with logo +.header-with-logo { + margin-bottom: 4rem; + + .logo-title-container { + display: flex; + align-items: center; + gap: 2rem; + margin-bottom: 3rem; + } + + .logo-wrapper { + flex-shrink: 0; + + .logo { + width: 120px; + height: 120px; + filter: drop-shadow(0 4px 12px rgba(255, 255, 255, 0.3)); + @include smooth-transition(transform); + + &:hover { + transform: scale(1.05); + } + } + } + + .title-wrapper { + flex: 1; + + h1 { + font-size: 4.5rem; + font-weight: 700; + margin-bottom: 0.5rem; + @include text-shadow; + line-height: 1.2; + } + + .subtitle { + font-size: 2.2rem; + opacity: 0.8; + font-weight: 300; + } + } +} + // Loading Indicator #loading-indicator { position: fixed; @@ -75,6 +120,7 @@ main { // Header header { margin-bottom: 4rem; + height: auto !important; h1 { font-size: 5rem; @@ -91,7 +137,7 @@ header { } // Service Grid -.service-links { +.service-container { flex: 1; display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); @@ -139,22 +185,6 @@ header { } } -// Cast Media Player -cast-media-player { - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 150px; - background: rgba(0, 0, 0, 0.9); - backdrop-filter: blur(20px); - display: none; - - &.active { - display: block; - } -} - // Footer .frit-fit { text-align: center; @@ -206,7 +236,7 @@ cast-media-player { } } - .service-links { + .service-container { grid-template-columns: 1fr; gap: 2rem; } From c0dde0af04329ee6123d1acb602e449e05b9db5b Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Wed, 24 Dec 2025 13:53:06 +0100 Subject: [PATCH 03/35] fixup! Rename, restructure and restyle page --- pages/tenfoot.pug | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pages/tenfoot.pug b/pages/tenfoot.pug index ac16f44..f7e6274 100644 --- a/pages/tenfoot.pug +++ b/pages/tenfoot.pug @@ -7,27 +7,27 @@ block title block content +vspace("25px") section.service-container - a.service-card(tabindex="0" role="button" href=navigation[key]) + .service-card(tabindex="0" role="button" data-service="stregsystem") .service-icon 💵 .service-title Stregsystem .service-description Browse our collection of wares - .service-card(tabindex="1" role="button" data-service="movies") + .service-card(tabindex="1" role="button" data-service="songbook") .service-icon 🎼 .service-title Songbook .service-description Browse our collection of songs - .service-card(tabindex="2" role="button" data-service="tvshows") + .service-card(tabindex="2" role="button" data-service="events") .service-icon 📅 .service-title Events .service-description Stream your favorite series - .service-card(tabindex="2" role="button" data-service="tvshows") + .service-card(tabindex="3" role="button" data-service="links") .service-icon 🌐 .service-title Links .service-description See nice links - .service-card(tabindex="3" role="button" data-service="settings") + .service-card(tabindex="4" role="button" data-service="exit") .service-icon ➜] .service-title Exit .service-description Leave 10-foot display From d665d0f37648fd957ea212a543dea12da0c518eb Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 16:43:35 +0100 Subject: [PATCH 04/35] Adjust layout values --- styles/tenfoot.scss | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index 2a8cbcf..b7ca9c0 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -46,7 +46,7 @@ main { // Header with logo .header-with-logo { - margin-bottom: 4rem; + margin-bottom: 2rem; .logo-title-container { display: flex; @@ -74,7 +74,7 @@ main { flex: 1; h1 { - font-size: 4.5rem; + font-size: 3rem; font-weight: 700; margin-bottom: 0.5rem; @include text-shadow; @@ -82,7 +82,7 @@ main { } .subtitle { - font-size: 2.2rem; + font-size: 2rem; opacity: 0.8; font-weight: 300; } @@ -119,7 +119,7 @@ main { // Header header { - margin-bottom: 4rem; + margin-bottom: 3rem; height: auto !important; h1 { @@ -139,7 +139,8 @@ header { // Service Grid .service-container { flex: 1; - display: grid; + display: flex; + position: fixed; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 3rem; margin-bottom: 4rem; @@ -187,7 +188,7 @@ header { // Footer .frit-fit { - text-align: center; + text-align: left; font-size: 2rem; opacity: 0.6; padding: 2rem; From f3a0037ca5bed0dce6032156e9dbe523713bdd20 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 20:15:20 +0100 Subject: [PATCH 05/35] Re-adjust to make it fit better on smaller screen --- styles/tenfoot.scss | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index b7ca9c0..08ae2da 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -35,24 +35,26 @@ html { color: $text-color; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; overflow-x: hidden; + max-height: 100vh; + display: flex; + flex-direction: column; } - main { - max-height: 100vh; + flex: 1; display: flex; - flex-direction: row; - padding: 4rem; + flex-direction: column; + overflow: hidden; + //padding: 4rem; } // Header with logo .header-with-logo { - margin-bottom: 2rem; + padding: 1.5rem; .logo-title-container { display: flex; align-items: center; gap: 2rem; - margin-bottom: 3rem; } .logo-wrapper { @@ -76,7 +78,6 @@ main { h1 { font-size: 3rem; font-weight: 700; - margin-bottom: 0.5rem; @include text-shadow; line-height: 1.2; } @@ -119,7 +120,6 @@ main { // Header header { - margin-bottom: 3rem; height: auto !important; h1 { @@ -140,17 +140,17 @@ header { .service-container { flex: 1; display: flex; - position: fixed; + overflow-x: auto; + overflow-y: visible; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 3rem; - margin-bottom: 4rem; } .service-card { background: $card-bg; backdrop-filter: blur(10px); border-radius: 2rem; - padding: 3rem; + padding: 3em; @include smooth-transition; border: 2px solid $card-border; cursor: pointer; @@ -158,6 +158,9 @@ header { flex-direction: column; align-items: center; text-align: center; + font-size: clamp(0.1rem, 1vw, 6rem); + margin-bottom: 2rem; + margin-top: 2rem; &:hover, &:focus { @@ -168,19 +171,19 @@ header { } .service-icon { - font-size: 6rem; + font-size: 6em; margin-bottom: 2rem; filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); } .service-title { - font-size: 3rem; + font-size: 3em; font-weight: 600; margin-bottom: 1.5rem; } .service-description { - font-size: 1.8rem; + font-size: 1.8em; opacity: 0.9; line-height: 1.6; } From a576f3b4720326c2f0b45273cf07adb6381245e3 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 20:23:37 +0100 Subject: [PATCH 06/35] Scale size of service card --- styles/tenfoot.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index 08ae2da..87c971a 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -161,6 +161,7 @@ header { font-size: clamp(0.1rem, 1vw, 6rem); margin-bottom: 2rem; margin-top: 2rem; + height: 30em; &:hover, &:focus { From 1e3b7cae64b9b7718949bd48d42a79e0d2f4f294 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 20:53:17 +0100 Subject: [PATCH 07/35] Improve scaling of service cards --- styles/tenfoot.scss | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index 87c971a..074dc4c 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -39,6 +39,7 @@ html { display: flex; flex-direction: column; } + main { flex: 1; display: flex; @@ -140,13 +141,33 @@ header { .service-container { flex: 1; display: flex; - overflow-x: auto; - overflow-y: visible; - grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); + align-items: center; gap: 3rem; + + overflow-x: auto; + overflow-y: hidden; + + scroll-behavior: smooth; + scroll-snap-type: x mandatory; + + /* IE / Edge Legacy */ + -ms-overflow-style: none; +} + +.service-container::-webkit-scrollbar { + display: none; /* Chrome, Safari, Edge */ } .service-card { + flex: 0 0 auto; // prevents shrinking + margin: 0; + + display: flex; + flex-direction: column; + align-items: center; + gap: 2em; + + text-align: center; background: $card-bg; backdrop-filter: blur(10px); border-radius: 2rem; @@ -154,14 +175,9 @@ header { @include smooth-transition; border: 2px solid $card-border; cursor: pointer; - display: flex; - flex-direction: column; - align-items: center; - text-align: center; font-size: clamp(0.1rem, 1vw, 6rem); - margin-bottom: 2rem; - margin-top: 2rem; - height: 30em; + height: 25em; + width: 25em; &:hover, &:focus { @@ -173,14 +189,12 @@ header { .service-icon { font-size: 6em; - margin-bottom: 2rem; filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); } .service-title { font-size: 3em; font-weight: 600; - margin-bottom: 1.5rem; } .service-description { From 6e275ae4c91171e0f7b472a59e7e3a23cced2b96 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 21:01:08 +0100 Subject: [PATCH 08/35] Reorganize --- styles/tenfoot.scss | 65 +++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 43 deletions(-) diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index 074dc4c..e12aa1e 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -91,34 +91,6 @@ main { } } -// Loading Indicator -#loading-indicator { - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - z-index: 1000; - - &.spinner { - animation: spin 2s linear infinite; - } - - img { - width: 200px; - height: 200px; - filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.5)); - } -} - -@keyframes spin { - 0% { - transform: translate(-50%, -50%) rotate(0deg); - } - 100% { - transform: translate(-50%, -50%) rotate(360deg); - } -} - // Header header { height: auto !important; @@ -239,24 +211,31 @@ header { } } -// Responsive adjustments -@media (max-width: 1200px) { - main { - padding: 2rem; - } - header { - h1 { - font-size: 3.5rem; - } +// Loading Indicator +#loading-indicator { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 1000; - .subtitle { - font-size: 2rem; - } + &.spinner { + animation: spin 2s linear infinite; } - .service-container { - grid-template-columns: 1fr; - gap: 2rem; + img { + width: 200px; + height: 200px; + filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.5)); } } + +@keyframes spin { + 0% { + transform: translate(-50%, -50%) rotate(0deg); + } + 100% { + transform: translate(-50%, -50%) rotate(360deg); + } +} \ No newline at end of file From 250551e2f99df47852d74d9a69af098eecf476b6 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 21:48:11 +0100 Subject: [PATCH 09/35] Scroll screen to card --- scripts/tenfoot-navigation.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/tenfoot-navigation.js b/scripts/tenfoot-navigation.js index 1268f3d..3e7b441 100644 --- a/scripts/tenfoot-navigation.js +++ b/scripts/tenfoot-navigation.js @@ -101,6 +101,17 @@ class TenFootNavigator { } } +document.querySelectorAll('.service-card').forEach(card => { + card.addEventListener('focus', () => { + card.scrollIntoView({ + behavior: 'smooth', + inline: 'center', + block: 'nearest' + }); + }); +}); + + // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { From 8fc660dc4f5d7c2a0194a31928d04e34580209c0 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 21:48:42 +0100 Subject: [PATCH 10/35] Make header and footer scale properly --- styles/tenfoot.scss | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index e12aa1e..0c42591 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -50,20 +50,20 @@ main { // Header with logo .header-with-logo { - padding: 1.5rem; + padding: 1.5em; .logo-title-container { display: flex; align-items: center; - gap: 2rem; + gap: 2em; } .logo-wrapper { flex-shrink: 0; .logo { - width: 120px; - height: 120px; + width: 8em; + height: 8em; filter: drop-shadow(0 4px 12px rgba(255, 255, 255, 0.3)); @include smooth-transition(transform); @@ -94,16 +94,17 @@ main { // Header header { height: auto !important; + font-size: clamp(0.1rem, 2vh, 6rem); h1 { - font-size: 5rem; + font-size: 5em; font-weight: 700; - margin-bottom: 1rem; + margin-bottom: 0.2em; @include text-shadow; } .subtitle { - font-size: 2.5rem; + font-size: 2.5em; opacity: 0.8; font-weight: 300; } @@ -177,12 +178,14 @@ header { } // Footer +footer { + padding: 2rem; + margin-top: auto; +} .frit-fit { text-align: left; - font-size: 2rem; + font-size: 1.5em; opacity: 0.6; - padding: 2rem; - margin-top: auto; } // Focus indicators for accessibility From fa66463e257db48b0a843e48a3a8aa400a39bc88 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 21:49:13 +0100 Subject: [PATCH 11/35] Try to fix scroll issue The container contents is pushed off screen to the left --- styles/tenfoot.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index 0c42591..fd858fa 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -42,6 +42,7 @@ html { main { flex: 1; + padding-left: 100vw; // scuffed display: flex; flex-direction: column; overflow: hidden; @@ -122,6 +123,7 @@ header { scroll-behavior: smooth; scroll-snap-type: x mandatory; + padding-inline: 3rem; /* IE / Edge Legacy */ -ms-overflow-style: none; @@ -151,6 +153,7 @@ header { font-size: clamp(0.1rem, 1vw, 6rem); height: 25em; width: 25em; + scroll-margin-inline: 30rem; &:hover, &:focus { From de1fe7c2bc720c4c89a482ca5188e66f2dae5d96 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 22:15:54 +0100 Subject: [PATCH 12/35] Rename base layout files --- components/page_layout.pug | 31 +++++++++++++++++++ ..._layout_tenfoot.pug => tenfoot_layout.pug} | 0 pages/events.pug | 2 +- pages/index.pug | 2 +- pages/links.pug | 2 +- pages/offline.pug | 2 +- pages/songbook/index.pug | 2 +- pages/stregsystem.pug | 2 +- pages/tenfoot.pug | 2 +- 9 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 components/page_layout.pug rename components/{base_layout_tenfoot.pug => tenfoot_layout.pug} (100%) diff --git a/components/page_layout.pug b/components/page_layout.pug new file mode 100644 index 0000000..d03056d --- /dev/null +++ b/components/page_layout.pug @@ -0,0 +1,31 @@ +include core + +block pug_meta + +- const title = typeof page_title === 'string' ? `${page_title} - ${app_name}` : app_name; + +doctype html +html(lang="en") + +head(title) + block head + body + header + a.nav-trigger(href="#") + img.access-status-indicator(src="/media/flogo.svg" height="50") + fa-profile-widget + aside#sidebar-nav + ul.border-outer + each key in Object.keys(navigation) + .border-inner + a(href=navigation[key]) + li= key + button.darkmode-button darkmode + main + if show_load_indicator + #loading-indicator.spinner + img(width="200" src="/media/fstjerne.svg") + block content + if hide_frit_fit !== true + p.frit-fit #fritfit (for real) + +scripts + block scripts diff --git a/components/base_layout_tenfoot.pug b/components/tenfoot_layout.pug similarity index 100% rename from components/base_layout_tenfoot.pug rename to components/tenfoot_layout.pug diff --git a/pages/events.pug b/pages/events.pug index a20f80d..7484deb 100644 --- a/pages/events.pug +++ b/pages/events.pug @@ -1,4 +1,4 @@ -extends ../components/base_layout +extends ../components/page_layout block pug_meta - const page_title = "Events"; diff --git a/pages/index.pug b/pages/index.pug index c760387..e451cbe 100644 --- a/pages/index.pug +++ b/pages/index.pug @@ -1,4 +1,4 @@ -extends ../components/base_layout +extends ../components/page_layout block head link(rel="stylesheet" href="/styles/frontpage.scss") diff --git a/pages/links.pug b/pages/links.pug index bf162b9..74e4ffb 100644 --- a/pages/links.pug +++ b/pages/links.pug @@ -1,4 +1,4 @@ -extends ../components/base_layout +extends ../components/page_layout block head link(rel="stylesheet" href="/styles/links.scss") diff --git a/pages/offline.pug b/pages/offline.pug index 940a200..8a27199 100644 --- a/pages/offline.pug +++ b/pages/offline.pug @@ -1,4 +1,4 @@ -extends ../components/base_layout +extends ../components/page_layout block head link(rel="stylesheet", href="/styles/offline.scss") diff --git a/pages/songbook/index.pug b/pages/songbook/index.pug index 5dd0143..d0fd213 100644 --- a/pages/songbook/index.pug +++ b/pages/songbook/index.pug @@ -1,4 +1,4 @@ -extends ../../components/base_layout.pug +extends ../../components/page_layout block head link(rel="stylesheet" href="/styles/songbook.scss") script(type="module", src="/scripts/songbook.ts") diff --git a/pages/stregsystem.pug b/pages/stregsystem.pug index 35a6c3c..941c9c8 100644 --- a/pages/stregsystem.pug +++ b/pages/stregsystem.pug @@ -1,4 +1,4 @@ -extends ../components/base_layout +extends ../components/page_layout block pug_meta - const page_title = "Stregsystemet"; diff --git a/pages/tenfoot.pug b/pages/tenfoot.pug index f7e6274..a096e1a 100644 --- a/pages/tenfoot.pug +++ b/pages/tenfoot.pug @@ -1,4 +1,4 @@ -extends ../components/base_layout_tenfoot +extends ../components/tenfoot_layout block title h2 Welcome From 0c50be0713e98c1c7b9ecb1e15e57879f90f298a Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 22:35:53 +0100 Subject: [PATCH 13/35] Refactor keyboard navigation code --- components/base_layout.pug | 31 ------------------------------- scripts/tenfoot-navigation.js | 33 ++++++--------------------------- 2 files changed, 6 insertions(+), 58 deletions(-) delete mode 100644 components/base_layout.pug diff --git a/components/base_layout.pug b/components/base_layout.pug deleted file mode 100644 index d03056d..0000000 --- a/components/base_layout.pug +++ /dev/null @@ -1,31 +0,0 @@ -include core - -block pug_meta - -- const title = typeof page_title === 'string' ? `${page_title} - ${app_name}` : app_name; - -doctype html -html(lang="en") - +head(title) - block head - body - header - a.nav-trigger(href="#") - img.access-status-indicator(src="/media/flogo.svg" height="50") - fa-profile-widget - aside#sidebar-nav - ul.border-outer - each key in Object.keys(navigation) - .border-inner - a(href=navigation[key]) - li= key - button.darkmode-button darkmode - main - if show_load_indicator - #loading-indicator.spinner - img(width="200" src="/media/fstjerne.svg") - block content - if hide_frit_fit !== true - p.frit-fit #fritfit (for real) - +scripts - block scripts diff --git a/scripts/tenfoot-navigation.js b/scripts/tenfoot-navigation.js index 3e7b441..bf505cb 100644 --- a/scripts/tenfoot-navigation.js +++ b/scripts/tenfoot-navigation.js @@ -1,4 +1,3 @@ -// ten-foot-navigation.js // Keyboard navigation for 10-foot interface class TenFootNavigator { @@ -26,14 +25,8 @@ class TenFootNavigator { } } - getColumns() { - return window.innerWidth > 1200 ? Math.min(3, this.cards.length) : 1; - } - setupKeyboardNavigation() { document.addEventListener('keydown', (e) => { - const cols = this.getColumns(); - switch(e.key) { case 'ArrowRight': e.preventDefault(); @@ -45,16 +38,6 @@ class TenFootNavigator { this.focusCard((this.currentIndex - 1 + this.cards.length) % this.cards.length); break; - case 'ArrowDown': - e.preventDefault(); - this.focusCard(Math.min(this.currentIndex + cols, this.cards.length - 1)); - break; - - case 'ArrowUp': - e.preventDefault(); - this.focusCard(Math.max(this.currentIndex - cols, 0)); - break; - case 'Enter': e.preventDefault(); this.cards[this.currentIndex].click(); @@ -84,6 +67,12 @@ class TenFootNavigator { // Track focus changes card.addEventListener('focus', () => { this.currentIndex = index; + + card.scrollIntoView({ + behavior: 'smooth', + inline: 'center', + block: 'nearest' + }); }); }); } @@ -101,16 +90,6 @@ class TenFootNavigator { } } -document.querySelectorAll('.service-card').forEach(card => { - card.addEventListener('focus', () => { - card.scrollIntoView({ - behavior: 'smooth', - inline: 'center', - block: 'nearest' - }); - }); -}); - // Initialize when DOM is ready if (document.readyState === 'loading') { From 62b1e9aa9eaa0dc3b7d2d33f187d47e8ebbb1510 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 22:45:02 +0100 Subject: [PATCH 14/35] Remove comments and change innerTexts --- components/tenfoot_layout.pug | 1 - pages/tenfoot.pug | 4 ++-- scripts/tenfoot-navigation.js | 3 --- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/components/tenfoot_layout.pug b/components/tenfoot_layout.pug index 358caa9..8201eb0 100644 --- a/components/tenfoot_layout.pug +++ b/components/tenfoot_layout.pug @@ -12,7 +12,6 @@ html(lang="en") header.header-with-logo .logo-title-container .logo-wrapper - //img.big-logo(src="/media/flogo.svg" height="200") img.logo(src="/media/flogo_w.svg" alt="Logo") .title-wrapper h1= app_name diff --git a/pages/tenfoot.pug b/pages/tenfoot.pug index a096e1a..cea005a 100644 --- a/pages/tenfoot.pug +++ b/pages/tenfoot.pug @@ -20,12 +20,12 @@ block content .service-card(tabindex="2" role="button" data-service="events") .service-icon 📅 .service-title Events - .service-description Stream your favorite series + .service-description List upcoming events .service-card(tabindex="3" role="button" data-service="links") .service-icon 🌐 .service-title Links - .service-description See nice links + .service-description Look at nice links .service-card(tabindex="4" role="button" data-service="exit") .service-icon ➜] diff --git a/scripts/tenfoot-navigation.js b/scripts/tenfoot-navigation.js index bf505cb..2c04087 100644 --- a/scripts/tenfoot-navigation.js +++ b/scripts/tenfoot-navigation.js @@ -64,7 +64,6 @@ class TenFootNavigator { // Example: window.location.href = `/service/${service}`; }); - // Track focus changes card.addEventListener('focus', () => { this.currentIndex = index; @@ -91,7 +90,6 @@ class TenFootNavigator { } -// Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { new TenFootNavigator(); @@ -100,5 +98,4 @@ if (document.readyState === 'loading') { new TenFootNavigator(); } -// Export for use in other modules if needed export default TenFootNavigator; \ No newline at end of file From 46ff484e9f2eea2d97633d0a110ad5548fe4adf7 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 22:49:02 +0100 Subject: [PATCH 15/35] fixup! Rename base layout files --- util/template/song.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/template/song.pug b/util/template/song.pug index 05c2a6c..ce89c4b 100644 --- a/util/template/song.pug +++ b/util/template/song.pug @@ -1,4 +1,4 @@ -extends ../../../components/base_layout +extends ../../../components/page_layout block head link(rel="stylesheet" href="/styles/songbook.scss") link(rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css") From d69c2dfbea79eea9dbc393e54ad2975503e4918f Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 23:10:53 +0100 Subject: [PATCH 16/35] Remove vspace --- pages/tenfoot.pug | 1 - 1 file changed, 1 deletion(-) diff --git a/pages/tenfoot.pug b/pages/tenfoot.pug index cea005a..94806a7 100644 --- a/pages/tenfoot.pug +++ b/pages/tenfoot.pug @@ -5,7 +5,6 @@ block title .subtitle Select a service to continue block content - +vspace("25px") section.service-container .service-card(tabindex="0" role="button" data-service="stregsystem") .service-icon 💵 From 95df4289e0d284c256379743baef33710c0c74b4 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 25 Dec 2025 23:14:20 +0100 Subject: [PATCH 17/35] Rewrite to typescript --- components/tenfoot_layout.pug | 2 +- ...ot-navigation.js => tenfoot-navigation.ts} | 36 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) rename scripts/{tenfoot-navigation.js => tenfoot-navigation.ts} (69%) diff --git a/components/tenfoot_layout.pug b/components/tenfoot_layout.pug index 8201eb0..e0ace0b 100644 --- a/components/tenfoot_layout.pug +++ b/components/tenfoot_layout.pug @@ -36,5 +36,5 @@ html(lang="en") p.frit-fit #fritfit (for real) +scripts - script(type="module" src="/scripts/tenfoot-navigation.js") + script(type="module" src="/scripts/tenfoot-navigation.ts") block scripts \ No newline at end of file diff --git a/scripts/tenfoot-navigation.js b/scripts/tenfoot-navigation.ts similarity index 69% rename from scripts/tenfoot-navigation.js rename to scripts/tenfoot-navigation.ts index 2c04087..e97c3f4 100644 --- a/scripts/tenfoot-navigation.js +++ b/scripts/tenfoot-navigation.ts @@ -1,13 +1,20 @@ // Keyboard navigation for 10-foot interface +interface ServiceSelected { + service: string; +} + class TenFootNavigator { + private cards: NodeListOf; + private currentIndex: number; + constructor() { - this.cards = document.querySelectorAll('.service-card'); + this.cards = document.querySelectorAll('.service-card'); this.currentIndex = 0; this.init(); } - init() { + private init(): void { this.setupKeyboardNavigation(); this.setupClickHandlers(); this.handleLoading(); @@ -18,15 +25,15 @@ class TenFootNavigator { } } - focusCard(index) { + private focusCard(index: number): void { if (index >= 0 && index < this.cards.length) { this.cards[index].focus(); this.currentIndex = index; } } - setupKeyboardNavigation() { - document.addEventListener('keydown', (e) => { + private setupKeyboardNavigation(): void { + document.addEventListener('keydown', (e: KeyboardEvent) => { switch(e.key) { case 'ArrowRight': e.preventDefault(); @@ -46,17 +53,18 @@ class TenFootNavigator { }); } - setupClickHandlers() { - this.cards.forEach((card, index) => { + private setupClickHandlers(): void { + this.cards.forEach((card: HTMLElement, index: number) => { card.addEventListener('click', () => { - const service = card.dataset.service; - const title = card.querySelector('.service-title').textContent; + const service = card.dataset.service || ''; + const titleElement = card.querySelector('.service-title'); + const title = titleElement?.textContent || ''; console.log(`Selected: ${title} (${service})`); // Dispatch custom event for handling navigation - const event = new CustomEvent('serviceSelected', { - detail: { service, title, index } + const event = new CustomEvent('serviceSelected', { + detail: { service } }); document.dispatchEvent(event); @@ -76,7 +84,7 @@ class TenFootNavigator { }); } - handleLoading() { + private handleLoading(): void { const loadingIndicator = document.getElementById('loading-indicator'); if (loadingIndicator) { @@ -89,10 +97,12 @@ class TenFootNavigator { } } - if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { new TenFootNavigator(); + + //const songbook = pug.compileFile("/pages/songbook/index.pug") + //document.getElementById('app').innerHTML = homePage({ data: someData }); }); } else { new TenFootNavigator(); From 4cdc47aaf2dd96eef4203e8019d3e55b73b74b80 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 2 Jan 2026 14:47:05 +0100 Subject: [PATCH 18/35] Name UI components to 'menu10foot' --- components/tenfoot_layout.pug | 2 +- pages/tenfoot.pug | 42 +++++++++---------- ...{tenfoot-navigation.ts => tenfoot-menu.ts} | 35 +++++++++++----- styles/tenfoot.scss | 12 +++--- 4 files changed, 52 insertions(+), 39 deletions(-) rename scripts/{tenfoot-navigation.ts => tenfoot-menu.ts} (77%) diff --git a/components/tenfoot_layout.pug b/components/tenfoot_layout.pug index e0ace0b..54652fc 100644 --- a/components/tenfoot_layout.pug +++ b/components/tenfoot_layout.pug @@ -36,5 +36,5 @@ html(lang="en") p.frit-fit #fritfit (for real) +scripts - script(type="module" src="/scripts/tenfoot-navigation.ts") + script(type="module" src="/scripts/tenfoot-menu.ts") block scripts \ No newline at end of file diff --git a/pages/tenfoot.pug b/pages/tenfoot.pug index 94806a7..2408b43 100644 --- a/pages/tenfoot.pug +++ b/pages/tenfoot.pug @@ -5,28 +5,28 @@ block title .subtitle Select a service to continue block content - section.service-container - .service-card(tabindex="0" role="button" data-service="stregsystem") - .service-icon 💵 - .service-title Stregsystem - .service-description Browse our collection of wares + section.menu10foot + .menu10foot-card(tabindex="0" role="button" data-service="stregsystem") + .menu10foot-icon 💵 + .menu10foot-title Stregsystem + .menu10foot-description Browse our collection of wares - .service-card(tabindex="1" role="button" data-service="songbook") - .service-icon 🎼 - .service-title Songbook - .service-description Browse our collection of songs + .menu10foot-card(tabindex="1" role="button" data-service="songbook") + .menu10foot-icon 🎼 + .menu10foot-title Songbook + .menu10foot-description Browse our collection of songs - .service-card(tabindex="2" role="button" data-service="events") - .service-icon 📅 - .service-title Events - .service-description List upcoming events + .menu10foot-card(tabindex="2" role="button" data-service="events") + .menu10foot-icon 📅 + .menu10foot-title Events + .menu10foot-description List upcoming events - .service-card(tabindex="3" role="button" data-service="links") - .service-icon 🌐 - .service-title Links - .service-description Look at nice links + .menu10foot-card(tabindex="3" role="button" data-service="links") + .menu10foot-icon 🌐 + .menu10foot-title Links + .menu10foot-description Look at nice links - .service-card(tabindex="4" role="button" data-service="exit") - .service-icon ➜] - .service-title Exit - .service-description Leave 10-foot display + .menu10foot-card(tabindex="4" role="button" data-service="exit") + .menu10foot-icon ➜] + .menu10foot-title Exit + .menu10foot-description Leave 10-foot display diff --git a/scripts/tenfoot-navigation.ts b/scripts/tenfoot-menu.ts similarity index 77% rename from scripts/tenfoot-navigation.ts rename to scripts/tenfoot-menu.ts index e97c3f4..349f07e 100644 --- a/scripts/tenfoot-navigation.ts +++ b/scripts/tenfoot-menu.ts @@ -4,12 +4,12 @@ interface ServiceSelected { service: string; } -class TenFootNavigator { +class TenFootMenuNavigator { private cards: NodeListOf; private currentIndex: number; - constructor() { - this.cards = document.querySelectorAll('.service-card'); + constructor(cardContainer: Element) { + this.cards = cardContainer.querySelectorAll('.menu10foot-card'); this.currentIndex = 0; this.init(); } @@ -95,17 +95,30 @@ class TenFootNavigator { }); } } + + public async LoadPage(path: string) { + const app = document.getElementsByTagName('section')[0] + + try { + const response = await fetch(`/${path}.html`); + const html = await response.text(); + app.innerHTML = html; + } catch (error) { + app.innerHTML = '

Page not found

'; + } + } } -if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', () => { - new TenFootNavigator(); +const initMenu = () => { + const menuContainer = document.getElementsByClassName('menu10foot')[0]; + let nav = new TenFootMenuNavigator(menuContainer); +}; - //const songbook = pug.compileFile("/pages/songbook/index.pug") - //document.getElementById('app').innerHTML = homePage({ data: someData }); - }); +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initMenu); } else { - new TenFootNavigator(); + initMenu(); } -export default TenFootNavigator; \ No newline at end of file +// nav.LoadPage("links").then(r => console.log(r)); +export default TenFootMenuNavigator; \ No newline at end of file diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index fd858fa..5a65662 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -112,7 +112,7 @@ header { } // Service Grid -.service-container { +.menu10foot { flex: 1; display: flex; align-items: center; @@ -129,11 +129,11 @@ header { -ms-overflow-style: none; } -.service-container::-webkit-scrollbar { +.menu10foot::-webkit-scrollbar { display: none; /* Chrome, Safari, Edge */ } -.service-card { +.menu10foot-card { flex: 0 0 auto; // prevents shrinking margin: 0; @@ -163,17 +163,17 @@ header { @include card-shadow; } - .service-icon { + .menu10foot-icon { font-size: 6em; filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); } - .service-title { + .menu10foot-title { font-size: 3em; font-weight: 600; } - .service-description { + .menu10foot-description { font-size: 1.8em; opacity: 0.9; line-height: 1.6; From cf3229c6600ab6e37a2fc8c06ffe4118adffed1c Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 2 Jan 2026 15:55:41 +0100 Subject: [PATCH 19/35] Separate menu styling --- pages/tenfoot.pug | 1 + styles/menu10foot.scss | 92 ++++++++++++++++++++++++++++++++++++++++++ styles/tenfoot.scss | 73 --------------------------------- 3 files changed, 93 insertions(+), 73 deletions(-) create mode 100644 styles/menu10foot.scss diff --git a/pages/tenfoot.pug b/pages/tenfoot.pug index 2408b43..7473c5b 100644 --- a/pages/tenfoot.pug +++ b/pages/tenfoot.pug @@ -5,6 +5,7 @@ block title .subtitle Select a service to continue block content + link(rel="stylesheet" href="/styles/menu10foot.scss") section.menu10foot .menu10foot-card(tabindex="0" role="button" data-service="stregsystem") .menu10foot-icon 💵 diff --git a/styles/menu10foot.scss b/styles/menu10foot.scss new file mode 100644 index 0000000..e07a824 --- /dev/null +++ b/styles/menu10foot.scss @@ -0,0 +1,92 @@ +// ten-foot.scss +// Variables +$primary-gradient-start: #1a1a2e; +$primary-gradient-end: #16213e; +$text-color: #ffffff; +$card-bg: rgba(255, 255, 255, 0.1); +$card-bg-hover: rgba(255, 255, 255, 0.15); +$card-border: rgba(255, 255, 255, 0.2); +$card-border-hover: rgba(255, 255, 255, 0.4); +$focus-color: #00d4ff; + +// Mixins +@mixin card-shadow { + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4); +} + +@mixin text-shadow { + text-shadow: 0 4px 8px rgba(0, 0, 0, 0.5); +} + +@mixin smooth-transition($properties: all, $duration: 0.3s) { + transition: $properties $duration ease; +} + +// Service Grid +.menu10foot { + flex: 1; + display: flex; + align-items: center; + gap: 3rem; + + overflow-x: auto; + overflow-y: hidden; + + scroll-behavior: smooth; + scroll-snap-type: x mandatory; + padding-inline: 3rem; + + /* IE / Edge Legacy */ + -ms-overflow-style: none; +} + +.menu10foot::-webkit-scrollbar { + display: none; /* Chrome, Safari, Edge */ +} + +.menu10foot-card { + flex: 0 0 auto; // prevents shrinking + margin: 0; + + display: flex; + flex-direction: column; + align-items: center; + gap: 2em; + + text-align: center; + background: $card-bg; + backdrop-filter: blur(10px); + border-radius: 2rem; + padding: 3em; + @include smooth-transition; + border: 2px solid $card-border; + cursor: pointer; + font-size: clamp(0.1rem, 1vw, 6rem); + height: 25em; + width: 25em; + scroll-margin-inline: 30rem; + + &:hover, + &:focus { + transform: scale(1.05); + background: $card-bg-hover; + border-color: $card-border-hover; + @include card-shadow; + } + + .menu10foot-icon { + font-size: 6em; + filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); + } + + .menu10foot-title { + font-size: 3em; + font-weight: 600; + } + + .menu10foot-description { + font-size: 1.8em; + opacity: 0.9; + line-height: 1.6; + } +} diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss index 5a65662..16e1667 100644 --- a/styles/tenfoot.scss +++ b/styles/tenfoot.scss @@ -3,10 +3,6 @@ $primary-gradient-start: #1a1a2e; $primary-gradient-end: #16213e; $text-color: #ffffff; -$card-bg: rgba(255, 255, 255, 0.1); -$card-bg-hover: rgba(255, 255, 255, 0.15); -$card-border: rgba(255, 255, 255, 0.2); -$card-border-hover: rgba(255, 255, 255, 0.4); $focus-color: #00d4ff; // Mixins @@ -111,75 +107,6 @@ header { } } -// Service Grid -.menu10foot { - flex: 1; - display: flex; - align-items: center; - gap: 3rem; - - overflow-x: auto; - overflow-y: hidden; - - scroll-behavior: smooth; - scroll-snap-type: x mandatory; - padding-inline: 3rem; - - /* IE / Edge Legacy */ - -ms-overflow-style: none; -} - -.menu10foot::-webkit-scrollbar { - display: none; /* Chrome, Safari, Edge */ -} - -.menu10foot-card { - flex: 0 0 auto; // prevents shrinking - margin: 0; - - display: flex; - flex-direction: column; - align-items: center; - gap: 2em; - - text-align: center; - background: $card-bg; - backdrop-filter: blur(10px); - border-radius: 2rem; - padding: 3em; - @include smooth-transition; - border: 2px solid $card-border; - cursor: pointer; - font-size: clamp(0.1rem, 1vw, 6rem); - height: 25em; - width: 25em; - scroll-margin-inline: 30rem; - - &:hover, - &:focus { - transform: scale(1.05); - background: $card-bg-hover; - border-color: $card-border-hover; - @include card-shadow; - } - - .menu10foot-icon { - font-size: 6em; - filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); - } - - .menu10foot-title { - font-size: 3em; - font-weight: 600; - } - - .menu10foot-description { - font-size: 1.8em; - opacity: 0.9; - line-height: 1.6; - } -} - // Footer footer { padding: 2rem; From a698402ee0351447d766168c0a88c06e0b97271b Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 2 Jan 2026 17:18:36 +0100 Subject: [PATCH 20/35] Move script into folder --- components/tenfoot_layout.pug | 2 +- scripts/{tenfoot-menu.ts => tenfoot/menu.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename scripts/{tenfoot-menu.ts => tenfoot/menu.ts} (100%) diff --git a/components/tenfoot_layout.pug b/components/tenfoot_layout.pug index 54652fc..4eb83aa 100644 --- a/components/tenfoot_layout.pug +++ b/components/tenfoot_layout.pug @@ -36,5 +36,5 @@ html(lang="en") p.frit-fit #fritfit (for real) +scripts - script(type="module" src="/scripts/tenfoot-menu.ts") + script(type="module" src="/scripts/tenfoot/menu.ts") block scripts \ No newline at end of file diff --git a/scripts/tenfoot-menu.ts b/scripts/tenfoot/menu.ts similarity index 100% rename from scripts/tenfoot-menu.ts rename to scripts/tenfoot/menu.ts From 8f6f7e50aad924f86dfa650705d1f387dc3d6a08 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 2 Jan 2026 17:38:50 +0100 Subject: [PATCH 21/35] Add navigation class to manage menu --- components/tenfoot_layout.pug | 2 +- scripts/tenfoot/menu.ts | 53 +++----------- scripts/tenfoot/tenfoot-navigation.ts | 101 ++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 44 deletions(-) create mode 100644 scripts/tenfoot/tenfoot-navigation.ts diff --git a/components/tenfoot_layout.pug b/components/tenfoot_layout.pug index 4eb83aa..11e9fdf 100644 --- a/components/tenfoot_layout.pug +++ b/components/tenfoot_layout.pug @@ -36,5 +36,5 @@ html(lang="en") p.frit-fit #fritfit (for real) +scripts - script(type="module" src="/scripts/tenfoot/menu.ts") + script(type="module" src="/scripts/tenfoot/tenfoot-navigation.ts") block scripts \ No newline at end of file diff --git a/scripts/tenfoot/menu.ts b/scripts/tenfoot/menu.ts index 349f07e..affce61 100644 --- a/scripts/tenfoot/menu.ts +++ b/scripts/tenfoot/menu.ts @@ -1,23 +1,28 @@ // Keyboard navigation for 10-foot interface - interface ServiceSelected { service: string; } -class TenFootMenuNavigator { +export interface GotoPage { + navigateTo(page: string): Promise; +} + +export class TenFootMenu { private cards: NodeListOf; + private navigator: GotoPage; private currentIndex: number; - constructor(cardContainer: Element) { + constructor(navigator: GotoPage, cardContainer: Element) { + this.navigator = navigator; this.cards = cardContainer.querySelectorAll('.menu10foot-card'); this.currentIndex = 0; this.init(); } private init(): void { + console.log("Initialized Tenfoot Menu"); this.setupKeyboardNavigation(); this.setupClickHandlers(); - this.handleLoading(); // Focus first card on load if (this.cards.length > 0) { @@ -69,7 +74,7 @@ class TenFootMenuNavigator { document.dispatchEvent(event); // Add your navigation logic here - // Example: window.location.href = `/service/${service}`; + // navigator.navigateTo("links").then(r => console.log(r)); }); card.addEventListener('focus', () => { @@ -83,42 +88,4 @@ class TenFootMenuNavigator { }); }); } - - private handleLoading(): void { - const loadingIndicator = document.getElementById('loading-indicator'); - - if (loadingIndicator) { - window.addEventListener('load', () => { - setTimeout(() => { - loadingIndicator.style.display = 'none'; - }, 1500); - }); - } - } - - public async LoadPage(path: string) { - const app = document.getElementsByTagName('section')[0] - - try { - const response = await fetch(`/${path}.html`); - const html = await response.text(); - app.innerHTML = html; - } catch (error) { - app.innerHTML = '

Page not found

'; - } - } } - -const initMenu = () => { - const menuContainer = document.getElementsByClassName('menu10foot')[0]; - let nav = new TenFootMenuNavigator(menuContainer); -}; - -if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initMenu); -} else { - initMenu(); -} - -// nav.LoadPage("links").then(r => console.log(r)); -export default TenFootMenuNavigator; \ No newline at end of file diff --git a/scripts/tenfoot/tenfoot-navigation.ts b/scripts/tenfoot/tenfoot-navigation.ts new file mode 100644 index 0000000..6fc61ba --- /dev/null +++ b/scripts/tenfoot/tenfoot-navigation.ts @@ -0,0 +1,101 @@ +// Keyboard navigation for 10-foot interface + +import {TenFootMenu, GotoPage} from "./menu"; + +class TenFootNavigator implements GotoPage { + private currentPage: string; + + constructor() { + this.init(); + } + + private init(): void { + console.log("Loaded Tenfoot-navigation"); + + this.inputOverride(); + this.handleLoading(); + this.TryInstantiateMenu(); + } + + private inputOverride(): void { + document.addEventListener('keydown', (e: KeyboardEvent) => { + switch(e.key) { + case 'Enter': + break; + case 'Escape': + case 'BrowserBack': + e.preventDefault(); + break; + case 'MediaPlayPause': + break; + case 'MediaPlay': + break; + case 'MediaPause': + break; + case 'MediaStop': + break; + case 'MediaTrackNext': + break; + case 'MediaTrackPrevious': + break; + } + }); + } + + private handleLoading(): void { + const loadingIndicator = document.getElementById('loading-indicator'); + + if (loadingIndicator) { + window.addEventListener('load', () => { + setTimeout(() => { + loadingIndicator.style.display = 'none'; + }, 1500); + }); + } + } + + async navigateTo(page: string): Promise { + await this.LoadPage(page); + } + + async LoadPage(path: string) { + const app = document.getElementsByTagName('section')[0] + + try { + const response = await fetch(`/${path}.html`); + const html = await response.text(); + app.innerHTML = html; + + this.TryInstantiateMenu(); + } catch (error) { + app.innerHTML = '

Page not found

'; + } + } + + TryInstantiateMenu(){ + // Try load 10foot-menu handler + const initMenu = () => { + const menuContainer = document.getElementsByClassName('menu10foot')[0]; + let nav = new TenFootMenu(this, menuContainer); + }; + + // TODO: mby doesn't work for loading subpages + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initMenu); + } else { + initMenu(); + } + } +} + +const initNavigation = () => { + let nav = new TenFootNavigator(); +}; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initNavigation); +} else { + initNavigation(); +} + +export default TenFootNavigator; \ No newline at end of file From 169fd6b37cf51a50484892ad6c83aeb0e40f722b Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 2 Jan 2026 21:36:34 +0100 Subject: [PATCH 22/35] Make Logo navigate to frontpage --- components/tenfoot_layout.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/tenfoot_layout.pug b/components/tenfoot_layout.pug index 11e9fdf..5997ecf 100644 --- a/components/tenfoot_layout.pug +++ b/components/tenfoot_layout.pug @@ -11,7 +11,7 @@ html(lang="en") body header.header-with-logo .logo-title-container - .logo-wrapper + a.logo-wrapper(href="/") img.logo(src="/media/flogo_w.svg" alt="Logo") .title-wrapper h1= app_name From a7f2213638b24dcfa4652f554fa768028c2460a9 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 2 Jan 2026 21:47:25 +0100 Subject: [PATCH 23/35] Move tenfoot page into folder --- .pugrc.js | 2 +- pages/{tenfoot.pug => tenfoot/index.pug} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename pages/{tenfoot.pug => tenfoot/index.pug} (100%) diff --git a/.pugrc.js b/.pugrc.js index 3f4600a..4d90260 100644 --- a/.pugrc.js +++ b/.pugrc.js @@ -11,7 +11,7 @@ module.exports = { Events: "/pages/events.pug", Links: "/pages/links.pug", Offline: "/pages/offline.pug", - TenFoot: "/pages/tenfoot.pug", + TenFoot: "/pages/tenfoot/index.pug", }, links: { Slack: "https://fklubben.slack.com", diff --git a/pages/tenfoot.pug b/pages/tenfoot/index.pug similarity index 100% rename from pages/tenfoot.pug rename to pages/tenfoot/index.pug From 19e0c58e3a18b9e7d9ab38daf0b8413aaad81002 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 2 Jan 2026 21:48:29 +0100 Subject: [PATCH 24/35] Update page navigation There's not target on each button --- pages/tenfoot/index.pug | 12 ++++++------ scripts/tenfoot/menu.ts | 19 ++++++------------- scripts/tenfoot/tenfoot-navigation.ts | 11 +++++++++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pages/tenfoot/index.pug b/pages/tenfoot/index.pug index 7473c5b..c1d1d1b 100644 --- a/pages/tenfoot/index.pug +++ b/pages/tenfoot/index.pug @@ -1,4 +1,4 @@ -extends ../components/tenfoot_layout +extends ../../components/tenfoot_layout block title h2 Welcome @@ -7,27 +7,27 @@ block title block content link(rel="stylesheet" href="/styles/menu10foot.scss") section.menu10foot - .menu10foot-card(tabindex="0" role="button" data-service="stregsystem") + .menu10foot-card(tabindex="0" role="button" data-link="stregsystem") .menu10foot-icon 💵 .menu10foot-title Stregsystem .menu10foot-description Browse our collection of wares - .menu10foot-card(tabindex="1" role="button" data-service="songbook") + .menu10foot-card(tabindex="1" role="button" data-link="songbook") .menu10foot-icon 🎼 .menu10foot-title Songbook .menu10foot-description Browse our collection of songs - .menu10foot-card(tabindex="2" role="button" data-service="events") + .menu10foot-card(tabindex="2" role="button" data-link="events") .menu10foot-icon 📅 .menu10foot-title Events .menu10foot-description List upcoming events - .menu10foot-card(tabindex="3" role="button" data-service="links") + .menu10foot-card(tabindex="3" role="button" data-link="links") .menu10foot-icon 🌐 .menu10foot-title Links .menu10foot-description Look at nice links - .menu10foot-card(tabindex="4" role="button" data-service="exit") + .menu10foot-card(tabindex="4" role="button" data-link="//") .menu10foot-icon ➜] .menu10foot-title Exit .menu10foot-description Leave 10-foot display diff --git a/scripts/tenfoot/menu.ts b/scripts/tenfoot/menu.ts index affce61..22ac6be 100644 --- a/scripts/tenfoot/menu.ts +++ b/scripts/tenfoot/menu.ts @@ -9,11 +9,11 @@ export interface GotoPage { export class TenFootMenu { private cards: NodeListOf; - private navigator: GotoPage; + private nav: GotoPage; private currentIndex: number; constructor(navigator: GotoPage, cardContainer: Element) { - this.navigator = navigator; + this.nav = navigator; this.cards = cardContainer.querySelectorAll('.menu10foot-card'); this.currentIndex = 0; this.init(); @@ -60,21 +60,14 @@ export class TenFootMenu { private setupClickHandlers(): void { this.cards.forEach((card: HTMLElement, index: number) => { - card.addEventListener('click', () => { - const service = card.dataset.service || ''; + card.addEventListener('click', async () => { + const link = card.dataset.link || ''; const titleElement = card.querySelector('.service-title'); const title = titleElement?.textContent || ''; - console.log(`Selected: ${title} (${service})`); + console.log(`Selected: ${title} (${link})`); - // Dispatch custom event for handling navigation - const event = new CustomEvent('serviceSelected', { - detail: { service } - }); - document.dispatchEvent(event); - - // Add your navigation logic here - // navigator.navigateTo("links").then(r => console.log(r)); + await this.nav.navigateTo(link); }); card.addEventListener('focus', () => { diff --git a/scripts/tenfoot/tenfoot-navigation.ts b/scripts/tenfoot/tenfoot-navigation.ts index 6fc61ba..bcca810 100644 --- a/scripts/tenfoot/tenfoot-navigation.ts +++ b/scripts/tenfoot/tenfoot-navigation.ts @@ -58,11 +58,18 @@ class TenFootNavigator implements GotoPage { await this.LoadPage(page); } - async LoadPage(path: string) { + async LoadPage(tenfoot_page: string) { + // Special case of navigation + if (tenfoot_page == "//"){ + window.location.href = "/"; + }else if (tenfoot_page == "/"){ + tenfoot_page = "index"; + } + const app = document.getElementsByTagName('section')[0] try { - const response = await fetch(`/${path}.html`); + const response = await fetch(`/tenfoot/${tenfoot_page}.html`); const html = await response.text(); app.innerHTML = html; From 83bfb5aa23fd5bb4fb81db11a89fb8b96d82cdcb Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 2 Jan 2026 21:49:25 +0100 Subject: [PATCH 25/35] Make logo only restore to tenfoot --- components/tenfoot_layout.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/tenfoot_layout.pug b/components/tenfoot_layout.pug index 5997ecf..48ed550 100644 --- a/components/tenfoot_layout.pug +++ b/components/tenfoot_layout.pug @@ -11,7 +11,7 @@ html(lang="en") body header.header-with-logo .logo-title-container - a.logo-wrapper(href="/") + a.logo-wrapper(href="/tenfoot/") img.logo(src="/media/flogo_w.svg" alt="Logo") .title-wrapper h1= app_name From bfc44cf4de1ae05556062599e5f78d9b002f7373 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 9 Jan 2026 04:17:14 +0100 Subject: [PATCH 26/35] Rename css-classes --- components/service_menu.pug | 3 ++- styles/service-menu.scss | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/service_menu.pug b/components/service_menu.pug index fc5232a..2d9c301 100644 --- a/components/service_menu.pug +++ b/components/service_menu.pug @@ -1,7 +1,8 @@ mixin menu(links, target) link(rel="stylesheet" href="/styles/service-menu.scss") section.service-links.border-outer + section.service-menu.border-outer each key in Object.keys(links) - a(href=links[key] target=target) + a.service-link(href=links[key] target=target) .border-inner h3=key diff --git a/styles/service-menu.scss b/styles/service-menu.scss index 33e4124..8a387b4 100644 --- a/styles/service-menu.scss +++ b/styles/service-menu.scss @@ -1,4 +1,4 @@ -.service-links { +.service-menu { width: 50%; box-sizing: border-box; text-align: center; From 076969be813096d30ea607bc8e9859877f744c20 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 9 Jan 2026 19:06:02 +0100 Subject: [PATCH 27/35] Introduce localStorage to store 10-foot display --- components/page_layout.pug | 4 ++++ pages/tenfoot/toggle.pug | 13 +++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 pages/tenfoot/toggle.pug diff --git a/components/page_layout.pug b/components/page_layout.pug index d03056d..a3e7c93 100644 --- a/components/page_layout.pug +++ b/components/page_layout.pug @@ -28,4 +28,8 @@ html(lang="en") if hide_frit_fit !== true p.frit-fit #fritfit (for real) +scripts + script. + // Determine mode from localStorage (or default) + const tenFoot = localStorage.getItem('tenFoot') === '1'; + if (tenFoot) document.body.classList.add('ten-foot'); block scripts diff --git a/pages/tenfoot/toggle.pug b/pages/tenfoot/toggle.pug new file mode 100644 index 0000000..f053a2b --- /dev/null +++ b/pages/tenfoot/toggle.pug @@ -0,0 +1,13 @@ +include ../../components/core + +doctype html +html(lang="en") + body + script. + // Read current mode from localStorage + const tenFoot = localStorage.getItem('tenFoot') === '1'; + + localStorage.setItem('tenFoot', tenFoot ? '0' : '1'); + + // Redirect after flipping + window.location.href = '/'; From 2f391051a59bc08fed10e741f2af2f747479da47 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 9 Jan 2026 19:08:48 +0100 Subject: [PATCH 28/35] Add service icons and description to data --- .pugrc.js | 27 +++++++++++++-------------- components/page_layout.pug | 2 +- components/service_menu.pug | 6 +++++- styles/service-menu.scss | 4 ++++ 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/.pugrc.js b/.pugrc.js index 4d90260..7581da0 100644 --- a/.pugrc.js +++ b/.pugrc.js @@ -5,22 +5,21 @@ module.exports = { app_name: "Fappen", manifest: require('./manifest.json'), navigation: { - Frontpage: "/pages/index.pug", - Stregsystem: "/pages/stregsystem.pug", - Songbook: "/pages/songbook/index.pug", - Events: "/pages/events.pug", - Links: "/pages/links.pug", - Offline: "/pages/offline.pug", - TenFoot: "/pages/tenfoot/index.pug", + Frontpage: ["/pages/index.pug", "🏠", "Frontpage"], + Stregsystem: ["/pages/stregsystem.pug", "💵", "Browse our collection of wares"], + Songbook: ["/pages/songbook/index.pug", "🎼", "Browser our collection of songs"], + Events: ["/pages/events.pug", "📅", "List upcoming events"], + Links: ["/pages/links.pug", "🌐", "Look at nice links"], + Offline: ["/pages/offline.pug", "✈", "Enter offline-mode"], + TenFoot: ["/pages/tenfoot/toggle.pug", "➜]", "Toggle 10-foot display"], }, links: { - Slack: "https://fklubben.slack.com", - Discord: "https://discord.gg/6DBvANjs3g", - Facebook: "https://www.facebook.com/fklub", - Github: "https://github.com/f-klubben", - Fiki: "https://fklub.dk", - Stregsystem: "https://stregsystem.fklub.dk" - + Slack: ["https://fklubben.slack.com"], + Discord: ["https://discord.gg/6DBvANjs3g"], + Facebook: ["https://www.facebook.com/fklub"], + Github: ["https://github.com/f-klubben"], + Fiki: ["https://fklub.dk"], + Stregsystem: ["https://stregsystem.fklub.dk"] }, disable_worker: process.env.disable_worker === "true" || true, } diff --git a/components/page_layout.pug b/components/page_layout.pug index a3e7c93..5adae03 100644 --- a/components/page_layout.pug +++ b/components/page_layout.pug @@ -17,7 +17,7 @@ html(lang="en") ul.border-outer each key in Object.keys(navigation) .border-inner - a(href=navigation[key]) + a(href=navigation[key][0]) li= key button.darkmode-button darkmode main diff --git a/components/service_menu.pug b/components/service_menu.pug index 2d9c301..0074ca5 100644 --- a/components/service_menu.pug +++ b/components/service_menu.pug @@ -3,6 +3,10 @@ mixin menu(links, target) section.service-links.border-outer section.service-menu.border-outer each key in Object.keys(links) - a.service-link(href=links[key] target=target) + a.service-link(href=links[key][0] target=target) + if links[key].length > 1 + .service-icon=links[key][1] .border-inner h3=key + if links[key].length > 2 + .service-description=links[key][2] diff --git a/styles/service-menu.scss b/styles/service-menu.scss index 8a387b4..15e1f26 100644 --- a/styles/service-menu.scss +++ b/styles/service-menu.scss @@ -7,4 +7,8 @@ .service-body { padding: 1em; +} + +.service-icon, .service-description { + display: none; } \ No newline at end of file From 1f76753b7ef87c87b610b2123d6824369418f6a2 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 9 Jan 2026 19:09:32 +0100 Subject: [PATCH 29/35] fixup! Rename css-classes --- components/service_menu.pug | 1 - 1 file changed, 1 deletion(-) diff --git a/components/service_menu.pug b/components/service_menu.pug index 0074ca5..56b6116 100644 --- a/components/service_menu.pug +++ b/components/service_menu.pug @@ -1,6 +1,5 @@ mixin menu(links, target) link(rel="stylesheet" href="/styles/service-menu.scss") - section.service-links.border-outer section.service-menu.border-outer each key in Object.keys(links) a.service-link(href=links[key][0] target=target) From f68e1165dcc2f7d5d7e98191c5beb174d46a5dbc Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 9 Jan 2026 19:39:14 +0100 Subject: [PATCH 30/35] Add attempt to theme default page --- components/service_menu.pug | 1 + styles/service-menu_10foot.scss | 105 ++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 styles/service-menu_10foot.scss diff --git a/components/service_menu.pug b/components/service_menu.pug index 56b6116..59cde16 100644 --- a/components/service_menu.pug +++ b/components/service_menu.pug @@ -1,5 +1,6 @@ mixin menu(links, target) link(rel="stylesheet" href="/styles/service-menu.scss") + link(rel="stylesheet" href="/styles/service-menu_10foot.scss") section.service-menu.border-outer each key in Object.keys(links) a.service-link(href=links[key][0] target=target) diff --git a/styles/service-menu_10foot.scss b/styles/service-menu_10foot.scss new file mode 100644 index 0000000..f9fb24c --- /dev/null +++ b/styles/service-menu_10foot.scss @@ -0,0 +1,105 @@ +// ten-foot.scss +// Variables +$primary-gradient-start: #1a1a2e; +$primary-gradient-end: #16213e; +$text-color: #ffffff; +$card-bg: rgba(255, 255, 255, 0.1); +$card-bg-hover: rgba(255, 255, 255, 0.15); +$card-border: rgba(255, 255, 255, 0.2); +$card-border-hover: rgba(255, 255, 255, 0.4); +$focus-color: #00d4ff; + +// Mixins +@mixin card-shadow { + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4); +} + +@mixin text-shadow { + text-shadow: 0 4px 8px rgba(0, 0, 0, 0.5); +} + +@mixin smooth-transition($properties: all, $duration: 0.3s) { + transition: $properties $duration ease; +} + +// Only apply rules on 10-foot mode +body.ten-foot { + // Service Grid + .service-menu { + flex: 1; + display: flex; + align-items: center; + gap: 3rem; + + overflow-x: auto; + overflow-y: hidden; + + scroll-behavior: smooth; + scroll-snap-type: x mandatory; + padding-inline: 3rem; + + /* IE / Edge Legacy */ + -ms-overflow-style: none; + } + + .service-menu::-webkit-scrollbar { + display: none; /* Chrome, Safari, Edge */ + } + + .service-menu > a { + // Un-linkify + display: block; + text-decoration: none; + color: inherit; + } + + .service-menu > .service-link { + flex: 0 0 auto; // prevents shrinking + margin: 0; + + display: flex; + flex-direction: column; + align-items: center; + gap: 2em; + + text-align: center; + background: $card-bg; + backdrop-filter: blur(10px); + border-radius: 2rem; + padding: 3em; + @include smooth-transition; + border: 2px solid $card-border; + cursor: pointer; + font-size: clamp(0.1rem, 1vw, 6rem); + height: 25em; + width: 25em; + scroll-margin-inline: 30rem; + + &:hover, + &:focus { + transform: scale(1.05); + background: $card-bg-hover; + border-color: $card-border-hover; + @include card-shadow; + } + + div > h3 { + h3 { + font-size: 3em; + font-weight: 600; + } + } + + .service-icon { + font-size: 6em; + filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); + } + + .service-description { + font-size: 1.8em; + opacity: 0.9; + line-height: 1.6; + } + + } +} From aea584021a202d474872ef967a26bc798849bf88 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Sat, 10 Jan 2026 03:03:14 +0100 Subject: [PATCH 31/35] Add new base variant of style --- styles/base_10foot.scss | 67 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 styles/base_10foot.scss diff --git a/styles/base_10foot.scss b/styles/base_10foot.scss new file mode 100644 index 0000000..2797db9 --- /dev/null +++ b/styles/base_10foot.scss @@ -0,0 +1,67 @@ +body.ten-foot { + // Variables + $primary-gradient-start: #1a1a2e; + $primary-gradient-end: #16213e; + $text-color: #ffffff; + $focus-color: #00d4ff; + + body { + background: linear-gradient(135deg, $primary-gradient-start 0%, $primary-gradient-end 100%); + color: $text-color; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + overflow-x: hidden; + max-height: 100vh; + display: flex; + flex-direction: column; + } + + main { + flex: 1; + padding-left: 100vw; // scuffed + display: flex; + flex-direction: column; + overflow: hidden; + //padding: 4rem; + } + + .center { + text-align: center; + } + + .flex-center { + align-content: center; + justify-content: center; + } + + /* + Header & navigation + */ + + header { + display: none; + } + + .spinner { + animation: rotation 5s infinite linear; + } + + @keyframes rotation { + from { + transform: rotate(0deg); + } + to { + transform: rotate(359deg); + } + } + + /* Border style simulating html tables */ + .border-outer { + border: inherit !important; + } + + .border-inner { + margin: inherit !important; + border: inherit !important; + } +} + From d4df131f626f10803598a4e3e8ba64e708a04b45 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Sat, 10 Jan 2026 03:04:09 +0100 Subject: [PATCH 32/35] Only load part of file --- scripts/tenfoot/tenfoot-navigation.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/scripts/tenfoot/tenfoot-navigation.ts b/scripts/tenfoot/tenfoot-navigation.ts index bcca810..189110d 100644 --- a/scripts/tenfoot/tenfoot-navigation.ts +++ b/scripts/tenfoot/tenfoot-navigation.ts @@ -69,9 +69,23 @@ class TenFootNavigator implements GotoPage { const app = document.getElementsByTagName('section')[0] try { - const response = await fetch(`/tenfoot/${tenfoot_page}.html`); - const html = await response.text(); - app.innerHTML = html; + await fetch(`/${tenfoot_page}.html`) + .then(response => response.text()) + .then(html => { + // Parse the HTML string into a document + const parser = new DOMParser(); + const doc = parser.parseFromString(html, 'text/html'); + + // Extract the
element + const mainContent = doc.querySelector('main'); + console.log(mainContent); + + if (mainContent) { + // Inject only the inner content of
+ app.innerHTML = mainContent.innerHTML; + } + } + ); this.TryInstantiateMenu(); } catch (error) { From ce284adc798169654670fbd4ff378c735231af46 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Sat, 10 Jan 2026 03:04:28 +0100 Subject: [PATCH 33/35] Remove old menu --- pages/tenfoot/index.pug | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/pages/tenfoot/index.pug b/pages/tenfoot/index.pug index c1d1d1b..3615c74 100644 --- a/pages/tenfoot/index.pug +++ b/pages/tenfoot/index.pug @@ -7,27 +7,3 @@ block title block content link(rel="stylesheet" href="/styles/menu10foot.scss") section.menu10foot - .menu10foot-card(tabindex="0" role="button" data-link="stregsystem") - .menu10foot-icon 💵 - .menu10foot-title Stregsystem - .menu10foot-description Browse our collection of wares - - .menu10foot-card(tabindex="1" role="button" data-link="songbook") - .menu10foot-icon 🎼 - .menu10foot-title Songbook - .menu10foot-description Browse our collection of songs - - .menu10foot-card(tabindex="2" role="button" data-link="events") - .menu10foot-icon 📅 - .menu10foot-title Events - .menu10foot-description List upcoming events - - .menu10foot-card(tabindex="3" role="button" data-link="links") - .menu10foot-icon 🌐 - .menu10foot-title Links - .menu10foot-description Look at nice links - - .menu10foot-card(tabindex="4" role="button" data-link="//") - .menu10foot-icon ➜] - .menu10foot-title Exit - .menu10foot-description Leave 10-foot display From 32c68014342022f99e36e0ec08d7fd788c62c67c Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Tue, 22 Sep 2026 14:00:18 +0200 Subject: [PATCH 34/35] Remove separate 10foot menus, update shared css --- .pugrc.js | 6 +- components/page_layout.pug | 13 +- components/tenfoot_layout.pug | 40 ------ media/flogo_w.svg | 77 ------------ pages/tenfoot/index.pug | 9 -- pages/tenfoot/toggle.pug | 12 +- scripts/index.ts | 40 ++++++ scripts/tenfoot/menu.ts | 84 ------------- scripts/tenfoot/tenfoot-navigation.ts | 122 ------------------ styles/base_10foot.scss | 32 +++-- styles/menu10foot.scss | 92 -------------- styles/service-menu_10foot.scss | 38 +++--- styles/tenfoot.scss | 174 -------------------------- 13 files changed, 100 insertions(+), 639 deletions(-) delete mode 100644 components/tenfoot_layout.pug delete mode 100644 media/flogo_w.svg delete mode 100644 pages/tenfoot/index.pug delete mode 100644 scripts/tenfoot/menu.ts delete mode 100644 scripts/tenfoot/tenfoot-navigation.ts delete mode 100644 styles/menu10foot.scss delete mode 100644 styles/tenfoot.scss diff --git a/.pugrc.js b/.pugrc.js index 7581da0..d10d0b9 100644 --- a/.pugrc.js +++ b/.pugrc.js @@ -5,13 +5,13 @@ module.exports = { app_name: "Fappen", manifest: require('./manifest.json'), navigation: { - Frontpage: ["/pages/index.pug", "🏠", "Frontpage"], + Frontpage: ["/pages/index.pug", "🏠", "Go to the front page"], Stregsystem: ["/pages/stregsystem.pug", "💵", "Browse our collection of wares"], - Songbook: ["/pages/songbook/index.pug", "🎼", "Browser our collection of songs"], + Songbook: ["/pages/songbook/index.pug", "🎼", "Browse our collection of songs"], Events: ["/pages/events.pug", "📅", "List upcoming events"], Links: ["/pages/links.pug", "🌐", "Look at nice links"], Offline: ["/pages/offline.pug", "✈", "Enter offline-mode"], - TenFoot: ["/pages/tenfoot/toggle.pug", "➜]", "Toggle 10-foot display"], + TenFoot: ["/pages/tenfoot/toggle.pug", "➜", "Toggle 10-foot display"], }, links: { Slack: ["https://fklubben.slack.com"], diff --git a/components/page_layout.pug b/components/page_layout.pug index 5adae03..67f7c56 100644 --- a/components/page_layout.pug +++ b/components/page_layout.pug @@ -7,6 +7,15 @@ block pug_meta doctype html html(lang="en") +head(title) + link(rel="stylesheet" href="/styles/base_10foot.scss") + script. + try { + if (localStorage.getItem('tenFoot') === '1') { + document.documentElement.classList.add('ten-foot'); + } + } catch (error) { + console.warn('Unable to restore display mode.', error); + } block head body header @@ -28,8 +37,4 @@ html(lang="en") if hide_frit_fit !== true p.frit-fit #fritfit (for real) +scripts - script. - // Determine mode from localStorage (or default) - const tenFoot = localStorage.getItem('tenFoot') === '1'; - if (tenFoot) document.body.classList.add('ten-foot'); block scripts diff --git a/components/tenfoot_layout.pug b/components/tenfoot_layout.pug deleted file mode 100644 index 48ed550..0000000 --- a/components/tenfoot_layout.pug +++ /dev/null @@ -1,40 +0,0 @@ -include core - -block pug_meta - -- const title = typeof page_title === 'string' ? `${page_title} - ${app_name}` : app_name; - -doctype html -html(lang="en") - +head(title) - link(rel="stylesheet" href="/styles/tenfoot.scss") - body - header.header-with-logo - .logo-title-container - a.logo-wrapper(href="/tenfoot/") - img.logo(src="/media/flogo_w.svg" alt="Logo") - .title-wrapper - h1= app_name - block title - - main - if show_load_indicator - #loading-indicator.spinner - img(width="200" src="/media/fstjerne.svg") - - .nav-hint - span Navigate with - kbd ↑ - kbd ↓ - kbd ← - kbd → - kbd Enter - block content - - footer - if hide_frit_fit !== true - p.frit-fit #fritfit (for real) - - +scripts - script(type="module" src="/scripts/tenfoot/tenfoot-navigation.ts") - block scripts \ No newline at end of file diff --git a/media/flogo_w.svg b/media/flogo_w.svg deleted file mode 100644 index 4d54b7d..0000000 --- a/media/flogo_w.svg +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pages/tenfoot/index.pug b/pages/tenfoot/index.pug deleted file mode 100644 index 3615c74..0000000 --- a/pages/tenfoot/index.pug +++ /dev/null @@ -1,9 +0,0 @@ -extends ../../components/tenfoot_layout - -block title - h2 Welcome - .subtitle Select a service to continue - -block content - link(rel="stylesheet" href="/styles/menu10foot.scss") - section.menu10foot diff --git a/pages/tenfoot/toggle.pug b/pages/tenfoot/toggle.pug index f053a2b..2f1c55d 100644 --- a/pages/tenfoot/toggle.pug +++ b/pages/tenfoot/toggle.pug @@ -4,10 +4,10 @@ doctype html html(lang="en") body script. - // Read current mode from localStorage - const tenFoot = localStorage.getItem('tenFoot') === '1'; - - localStorage.setItem('tenFoot', tenFoot ? '0' : '1'); - - // Redirect after flipping + try { + const tenFoot = localStorage.getItem('tenFoot') === '1'; + localStorage.setItem('tenFoot', tenFoot ? '0' : '1'); + } catch (error) { + console.warn('Unable to change display mode.', error); + } window.location.href = '/'; diff --git a/scripts/index.ts b/scripts/index.ts index 2308777..75582ed 100644 --- a/scripts/index.ts +++ b/scripts/index.ts @@ -47,6 +47,45 @@ function toggle_sidebar() { else sidebar.classList.add('active'); } + +function init_tenfoot_navigation() { + if (!document.documentElement.classList.contains('ten-foot')) return; + + const links = Array.from(document.querySelectorAll('.service-menu .service-link')); + if (links.length === 0) return; + + document.addEventListener('keydown', event => { + if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement || event.target instanceof HTMLSelectElement) return; + + const current_index = links.indexOf(document.activeElement as HTMLAnchorElement); + let next_index: number | undefined; + + switch (event.key) { + case 'ArrowRight': + case 'ArrowDown': + next_index = current_index < 0 ? 0 : (current_index + 1) % links.length; + break; + case 'ArrowLeft': + case 'ArrowUp': + next_index = current_index < 0 ? links.length - 1 : (current_index - 1 + links.length) % links.length; + break; + case 'Home': + next_index = 0; + break; + case 'End': + next_index = links.length - 1; + break; + } + + if (next_index === undefined) return; + event.preventDefault(); + links[next_index].focus(); + links[next_index].scrollIntoView({behavior: 'smooth', inline: 'center', block: 'nearest'}); + }); + + links[0].focus(); +} + function toggle_darkmode(){ let theme = document.body.classList.toggle("dark-theme")? "dark" : "light"; localStorage.setItem("theme", theme); @@ -83,6 +122,7 @@ void (() => { ?.forEach(node => { node.addEventListener('click', toggle_sidebar); }); + init_tenfoot_navigation(); /* Dark Mode stuff */ diff --git a/scripts/tenfoot/menu.ts b/scripts/tenfoot/menu.ts deleted file mode 100644 index 22ac6be..0000000 --- a/scripts/tenfoot/menu.ts +++ /dev/null @@ -1,84 +0,0 @@ -// Keyboard navigation for 10-foot interface -interface ServiceSelected { - service: string; -} - -export interface GotoPage { - navigateTo(page: string): Promise; -} - -export class TenFootMenu { - private cards: NodeListOf; - private nav: GotoPage; - private currentIndex: number; - - constructor(navigator: GotoPage, cardContainer: Element) { - this.nav = navigator; - this.cards = cardContainer.querySelectorAll('.menu10foot-card'); - this.currentIndex = 0; - this.init(); - } - - private init(): void { - console.log("Initialized Tenfoot Menu"); - this.setupKeyboardNavigation(); - this.setupClickHandlers(); - - // Focus first card on load - if (this.cards.length > 0) { - this.focusCard(0); - } - } - - private focusCard(index: number): void { - if (index >= 0 && index < this.cards.length) { - this.cards[index].focus(); - this.currentIndex = index; - } - } - - private setupKeyboardNavigation(): void { - document.addEventListener('keydown', (e: KeyboardEvent) => { - switch(e.key) { - case 'ArrowRight': - e.preventDefault(); - this.focusCard((this.currentIndex + 1) % this.cards.length); - break; - - case 'ArrowLeft': - e.preventDefault(); - this.focusCard((this.currentIndex - 1 + this.cards.length) % this.cards.length); - break; - - case 'Enter': - e.preventDefault(); - this.cards[this.currentIndex].click(); - break; - } - }); - } - - private setupClickHandlers(): void { - this.cards.forEach((card: HTMLElement, index: number) => { - card.addEventListener('click', async () => { - const link = card.dataset.link || ''; - const titleElement = card.querySelector('.service-title'); - const title = titleElement?.textContent || ''; - - console.log(`Selected: ${title} (${link})`); - - await this.nav.navigateTo(link); - }); - - card.addEventListener('focus', () => { - this.currentIndex = index; - - card.scrollIntoView({ - behavior: 'smooth', - inline: 'center', - block: 'nearest' - }); - }); - }); - } -} diff --git a/scripts/tenfoot/tenfoot-navigation.ts b/scripts/tenfoot/tenfoot-navigation.ts deleted file mode 100644 index 189110d..0000000 --- a/scripts/tenfoot/tenfoot-navigation.ts +++ /dev/null @@ -1,122 +0,0 @@ -// Keyboard navigation for 10-foot interface - -import {TenFootMenu, GotoPage} from "./menu"; - -class TenFootNavigator implements GotoPage { - private currentPage: string; - - constructor() { - this.init(); - } - - private init(): void { - console.log("Loaded Tenfoot-navigation"); - - this.inputOverride(); - this.handleLoading(); - this.TryInstantiateMenu(); - } - - private inputOverride(): void { - document.addEventListener('keydown', (e: KeyboardEvent) => { - switch(e.key) { - case 'Enter': - break; - case 'Escape': - case 'BrowserBack': - e.preventDefault(); - break; - case 'MediaPlayPause': - break; - case 'MediaPlay': - break; - case 'MediaPause': - break; - case 'MediaStop': - break; - case 'MediaTrackNext': - break; - case 'MediaTrackPrevious': - break; - } - }); - } - - private handleLoading(): void { - const loadingIndicator = document.getElementById('loading-indicator'); - - if (loadingIndicator) { - window.addEventListener('load', () => { - setTimeout(() => { - loadingIndicator.style.display = 'none'; - }, 1500); - }); - } - } - - async navigateTo(page: string): Promise { - await this.LoadPage(page); - } - - async LoadPage(tenfoot_page: string) { - // Special case of navigation - if (tenfoot_page == "//"){ - window.location.href = "/"; - }else if (tenfoot_page == "/"){ - tenfoot_page = "index"; - } - - const app = document.getElementsByTagName('section')[0] - - try { - await fetch(`/${tenfoot_page}.html`) - .then(response => response.text()) - .then(html => { - // Parse the HTML string into a document - const parser = new DOMParser(); - const doc = parser.parseFromString(html, 'text/html'); - - // Extract the
element - const mainContent = doc.querySelector('main'); - console.log(mainContent); - - if (mainContent) { - // Inject only the inner content of
- app.innerHTML = mainContent.innerHTML; - } - } - ); - - this.TryInstantiateMenu(); - } catch (error) { - app.innerHTML = '

Page not found

'; - } - } - - TryInstantiateMenu(){ - // Try load 10foot-menu handler - const initMenu = () => { - const menuContainer = document.getElementsByClassName('menu10foot')[0]; - let nav = new TenFootMenu(this, menuContainer); - }; - - // TODO: mby doesn't work for loading subpages - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initMenu); - } else { - initMenu(); - } - } -} - -const initNavigation = () => { - let nav = new TenFootNavigator(); -}; - -if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initNavigation); -} else { - initNavigation(); -} - -export default TenFootNavigator; \ No newline at end of file diff --git a/styles/base_10foot.scss b/styles/base_10foot.scss index 2797db9..8457778 100644 --- a/styles/base_10foot.scss +++ b/styles/base_10foot.scss @@ -1,27 +1,34 @@ -body.ten-foot { - // Variables +html.ten-foot { $primary-gradient-start: #1a1a2e; $primary-gradient-end: #16213e; $text-color: #ffffff; $focus-color: #00d4ff; + &, body { background: linear-gradient(135deg, $primary-gradient-start 0%, $primary-gradient-end 100%); color: $text-color; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; overflow-x: hidden; - max-height: 100vh; + } + + body { + height: 100dvh; display: flex; flex-direction: column; } main { flex: 1; - padding-left: 100vw; // scuffed + padding: clamp(1rem, 4vw, 4rem); display: flex; flex-direction: column; overflow: hidden; - //padding: 4rem; + align-items: stretch; + } + + .big-logo { + display: none; } .center { @@ -33,10 +40,6 @@ body.ten-foot { justify-content: center; } - /* - Header & navigation - */ - header { display: none; } @@ -54,14 +57,17 @@ body.ten-foot { } } - /* Border style simulating html tables */ .border-outer { border: inherit !important; } .border-inner { - margin: inherit !important; - border: inherit !important; + margin: 0 !important; + border: 0 !important; } -} + *:focus { + outline: 4px solid $focus-color; + outline-offset: 4px; + } +} diff --git a/styles/menu10foot.scss b/styles/menu10foot.scss deleted file mode 100644 index e07a824..0000000 --- a/styles/menu10foot.scss +++ /dev/null @@ -1,92 +0,0 @@ -// ten-foot.scss -// Variables -$primary-gradient-start: #1a1a2e; -$primary-gradient-end: #16213e; -$text-color: #ffffff; -$card-bg: rgba(255, 255, 255, 0.1); -$card-bg-hover: rgba(255, 255, 255, 0.15); -$card-border: rgba(255, 255, 255, 0.2); -$card-border-hover: rgba(255, 255, 255, 0.4); -$focus-color: #00d4ff; - -// Mixins -@mixin card-shadow { - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4); -} - -@mixin text-shadow { - text-shadow: 0 4px 8px rgba(0, 0, 0, 0.5); -} - -@mixin smooth-transition($properties: all, $duration: 0.3s) { - transition: $properties $duration ease; -} - -// Service Grid -.menu10foot { - flex: 1; - display: flex; - align-items: center; - gap: 3rem; - - overflow-x: auto; - overflow-y: hidden; - - scroll-behavior: smooth; - scroll-snap-type: x mandatory; - padding-inline: 3rem; - - /* IE / Edge Legacy */ - -ms-overflow-style: none; -} - -.menu10foot::-webkit-scrollbar { - display: none; /* Chrome, Safari, Edge */ -} - -.menu10foot-card { - flex: 0 0 auto; // prevents shrinking - margin: 0; - - display: flex; - flex-direction: column; - align-items: center; - gap: 2em; - - text-align: center; - background: $card-bg; - backdrop-filter: blur(10px); - border-radius: 2rem; - padding: 3em; - @include smooth-transition; - border: 2px solid $card-border; - cursor: pointer; - font-size: clamp(0.1rem, 1vw, 6rem); - height: 25em; - width: 25em; - scroll-margin-inline: 30rem; - - &:hover, - &:focus { - transform: scale(1.05); - background: $card-bg-hover; - border-color: $card-border-hover; - @include card-shadow; - } - - .menu10foot-icon { - font-size: 6em; - filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); - } - - .menu10foot-title { - font-size: 3em; - font-weight: 600; - } - - .menu10foot-description { - font-size: 1.8em; - opacity: 0.9; - line-height: 1.6; - } -} diff --git a/styles/service-menu_10foot.scss b/styles/service-menu_10foot.scss index f9fb24c..6d75478 100644 --- a/styles/service-menu_10foot.scss +++ b/styles/service-menu_10foot.scss @@ -23,20 +23,21 @@ $focus-color: #00d4ff; } // Only apply rules on 10-foot mode -body.ten-foot { +html.ten-foot { // Service Grid .service-menu { + width: 100%; flex: 1; display: flex; align-items: center; - gap: 3rem; + gap: clamp(2rem, 3vw, 4rem); overflow-x: auto; overflow-y: hidden; scroll-behavior: smooth; scroll-snap-type: x mandatory; - padding-inline: 3rem; + padding-inline: clamp(1rem, 3vw, 3rem); /* IE / Edge Legacy */ -ms-overflow-style: none; @@ -63,6 +64,7 @@ body.ten-foot { gap: 2em; text-align: center; + box-sizing: border-box; background: $card-bg; backdrop-filter: blur(10px); border-radius: 2rem; @@ -70,34 +72,40 @@ body.ten-foot { @include smooth-transition; border: 2px solid $card-border; cursor: pointer; - font-size: clamp(0.1rem, 1vw, 6rem); - height: 25em; - width: 25em; - scroll-margin-inline: 30rem; + font-size: clamp(0.75rem, 1vw, 1.25rem); + min-height: clamp(24rem, 62vh, 40rem); + width: clamp(20rem, 25vw, 30rem); + scroll-margin-inline: 3rem; + scroll-snap-align: center; + justify-content: center; &:hover, - &:focus { + &:focus-visible { transform: scale(1.05); background: $card-bg-hover; - border-color: $card-border-hover; + border-color: $focus-color; @include card-shadow; + z-index: 1; } - div > h3 { - h3 { - font-size: 3em; - font-weight: 600; - } + h3 { + font-size: 3em; + font-weight: 600; + line-height: 1.15; + margin: 0; } .service-icon { + display: block; font-size: 6em; filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3)); } .service-description { + display: block; font-size: 1.8em; - opacity: 0.9; + opacity: 0.95; + font-weight: 500; line-height: 1.6; } diff --git a/styles/tenfoot.scss b/styles/tenfoot.scss deleted file mode 100644 index 16e1667..0000000 --- a/styles/tenfoot.scss +++ /dev/null @@ -1,174 +0,0 @@ -// ten-foot.scss -// Variables -$primary-gradient-start: #1a1a2e; -$primary-gradient-end: #16213e; -$text-color: #ffffff; -$focus-color: #00d4ff; - -// Mixins -@mixin card-shadow { - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4); -} - -@mixin text-shadow { - text-shadow: 0 4px 8px rgba(0, 0, 0, 0.5); -} - -@mixin smooth-transition($properties: all, $duration: 0.3s) { - transition: $properties $duration ease; -} - -// Reset -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -// Body -html { - background: linear-gradient(135deg, $primary-gradient-start 0%, $primary-gradient-end 100%); - color: $text-color; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - overflow-x: hidden; - max-height: 100vh; - display: flex; - flex-direction: column; -} - -main { - flex: 1; - padding-left: 100vw; // scuffed - display: flex; - flex-direction: column; - overflow: hidden; - //padding: 4rem; -} - -// Header with logo -.header-with-logo { - padding: 1.5em; - - .logo-title-container { - display: flex; - align-items: center; - gap: 2em; - } - - .logo-wrapper { - flex-shrink: 0; - - .logo { - width: 8em; - height: 8em; - filter: drop-shadow(0 4px 12px rgba(255, 255, 255, 0.3)); - @include smooth-transition(transform); - - &:hover { - transform: scale(1.05); - } - } - } - - .title-wrapper { - flex: 1; - - h1 { - font-size: 3rem; - font-weight: 700; - @include text-shadow; - line-height: 1.2; - } - - .subtitle { - font-size: 2rem; - opacity: 0.8; - font-weight: 300; - } - } -} - -// Header -header { - height: auto !important; - font-size: clamp(0.1rem, 2vh, 6rem); - - h1 { - font-size: 5em; - font-weight: 700; - margin-bottom: 0.2em; - @include text-shadow; - } - - .subtitle { - font-size: 2.5em; - opacity: 0.8; - font-weight: 300; - } -} - -// Footer -footer { - padding: 2rem; - margin-top: auto; -} -.frit-fit { - text-align: left; - font-size: 1.5em; - opacity: 0.6; -} - -// Focus indicators for accessibility -*:focus { - outline: 4px solid $focus-color; - outline-offset: 4px; -} - -// Navigation hint -.nav-hint { - position: fixed; - bottom: 2rem; - right: 2rem; - font-size: 1.5rem; - opacity: 0.5; - display: flex; - gap: 1rem; - align-items: center; - - kbd { - background: rgba(255, 255, 255, 0.2); - padding: 0.5rem 1rem; - border-radius: 0.5rem; - font-family: monospace; - font-size: 1.3rem; - } -} - - -// Loading Indicator -#loading-indicator { - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - z-index: 1000; - - &.spinner { - animation: spin 2s linear infinite; - } - - img { - width: 200px; - height: 200px; - filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.5)); - } -} - -@keyframes spin { - 0% { - transform: translate(-50%, -50%) rotate(0deg); - } - 100% { - transform: translate(-50%, -50%) rotate(360deg); - } -} \ No newline at end of file From 014932efe7128b7f25e16c78ba84123f4909f36f Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Tue, 22 Sep 2026 14:00:49 +0200 Subject: [PATCH 35/35] Run build-songs before building --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1cf9dbc..2065433 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "scripts": { "start": "parcel pages/index.pug pages/songbook/songs/*.pug --dist-dir build/dist", "build-songs": "python util/build_songs.py", - "build": "parcel build pages/index.pug pages/songbook/songs/*.pug --dist-dir build/dist", + "build": "npm run build-songs && parcel build pages/index.pug pages/songbook/songs/*.pug --dist-dir build/dist", "cors-proxy": "node cors-proxy.js" }, "devDependencies": {