From 54cc31a03ad0a3e730d6466a3fd8182c846724d6 Mon Sep 17 00:00:00 2001 From: Alexander Bocken Date: Fri, 26 Dec 2025 17:34:34 +0100 Subject: [PATCH] refactor: extract language toggle into reusable components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create Toggle and LanguageToggle components to reduce code duplication and enable shared state across pages. - Add Toggle.svelte: Generic iOS-style toggle with customizable accent color - Add LanguageToggle.svelte: Language-specific toggle with localStorage persistence - Refactor rosary page to use new toggle components - Add language toggle to gebete page - Toggle state persists across both pages via localStorage - Reduce min-height of Ave Maria decades in monolingual mode (50vh → 30vh) --- src/lib/components/LanguageToggle.svelte | 39 ++++++++ src/lib/components/Toggle.svelte | 85 ++++++++++++++++ src/routes/glaube/gebete/+page.svelte | 6 ++ src/routes/glaube/rosenkranz/+page.svelte | 113 +++------------------- 4 files changed, 142 insertions(+), 101 deletions(-) create mode 100644 src/lib/components/LanguageToggle.svelte create mode 100644 src/lib/components/Toggle.svelte diff --git a/src/lib/components/LanguageToggle.svelte b/src/lib/components/LanguageToggle.svelte new file mode 100644 index 0000000..82a6793 --- /dev/null +++ b/src/lib/components/LanguageToggle.svelte @@ -0,0 +1,39 @@ + + + diff --git a/src/lib/components/Toggle.svelte b/src/lib/components/Toggle.svelte new file mode 100644 index 0000000..c8e1400 --- /dev/null +++ b/src/lib/components/Toggle.svelte @@ -0,0 +1,85 @@ + + + + +
+ +
diff --git a/src/routes/glaube/gebete/+page.svelte b/src/routes/glaube/gebete/+page.svelte index 0fb2d48..ebe212c 100644 --- a/src/routes/glaube/gebete/+page.svelte +++ b/src/routes/glaube/gebete/+page.svelte @@ -1,7 +1,9 @@

Gebete

+
diff --git a/src/routes/glaube/rosenkranz/+page.svelte b/src/routes/glaube/rosenkranz/+page.svelte index 980f491..31e7dfb 100644 --- a/src/routes/glaube/rosenkranz/+page.svelte +++ b/src/routes/glaube/rosenkranz/+page.svelte @@ -14,6 +14,8 @@ import RosaryFinalPrayer from "$lib/components/prayers/RosaryFinalPrayer.svelte" import BenedictusMedal from "$lib/components/BenedictusMedal.svelte"; import CounterButton from "$lib/components/CounterButton.svelte"; import BibleModal from "$lib/components/BibleModal.svelte"; +import Toggle from "$lib/components/Toggle.svelte"; +import LanguageToggle from "$lib/components/LanguageToggle.svelte"; export let data; @@ -115,25 +117,17 @@ const mysteryTitles = { // Toggle for including Luminous mysteries let includeLuminous = true; -// Create language context for prayer components -const { showLatin } = createLanguageContext(); -let showBilingual = true; - // Flag to prevent saving before we've loaded from localStorage let hasLoadedFromStorage = false; -// Sync checkbox with context -$: $showLatin = showBilingual; +// Create language context for prayer components (LanguageToggle will use this) +createLanguageContext(); -// Save toggle states to localStorage whenever they change (but only after initial load) +// Save luminous toggle state to localStorage whenever it changes (but only after initial load) $: if (typeof localStorage !== 'undefined' && hasLoadedFromStorage) { localStorage.setItem('rosary_includeLuminous', includeLuminous.toString()); } -$: if (typeof localStorage !== 'undefined' && hasLoadedFromStorage) { - localStorage.setItem('rosary_showBilingual', showBilingual.toString()); -} - // Function to get the appropriate mystery for a given weekday function getMysteryForWeekday(date, includeLuminous) { const dayOfWeek = date.getDay(); // 0 = Sunday, 1 = Monday, etc. @@ -274,18 +268,13 @@ const sectionPositions = { }; onMount(() => { - // Load toggle states from localStorage + // Load toggle state from localStorage const savedIncludeLuminous = localStorage.getItem('rosary_includeLuminous'); - const savedShowBilingual = localStorage.getItem('rosary_showBilingual'); if (savedIncludeLuminous !== null) { includeLuminous = savedIncludeLuminous === 'true'; } - if (savedShowBilingual !== null) { - showBilingual = savedShowBilingual === 'true'; - } - // Recalculate mystery based on loaded includeLuminous value todaysMystery = getMysteryForWeekday(new Date(), includeLuminous); selectMystery(todaysMystery); @@ -912,78 +901,6 @@ h1 { margin-bottom: 2rem; } -/* Luminous mysteries toggle */ -.luminous-toggle { - display: flex; - justify-content: center; - margin-bottom: 2rem; - max-width: 1200px; - margin-left: auto; - margin-right: auto; -} - -.luminous-toggle label { - display: flex; - align-items: center; - gap: 0.75rem; - cursor: pointer; - font-size: 0.95rem; - color: var(--nord4); -} - -@media(prefers-color-scheme: light) { - .luminous-toggle label { - color: var(--nord2); - } -} - -.luminous-toggle span { - user-select: none; -} - -/* iOS-style toggle switch */ -.luminous-toggle input[type="checkbox"] { - appearance: none; - -webkit-appearance: none; - width: 51px; - height: 31px; - background: var(--nord2); - border-radius: 31px; - position: relative; - cursor: pointer; - transition: background 0.3s ease; - outline: none; - border: none; - flex-shrink: 0; -} - -@media(prefers-color-scheme: light) { - .luminous-toggle input[type="checkbox"] { - background: var(--nord4); - } -} - -.luminous-toggle input[type="checkbox"]:checked { - background: var(--nord14); -} - -.luminous-toggle input[type="checkbox"]::before { - content: ''; - position: absolute; - width: 27px; - height: 27px; - border-radius: 50%; - top: 2px; - left: 2px; - background: white; - transition: transform 0.3s ease; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); -} - -.luminous-toggle input[type="checkbox"]:checked::before { - transform: translateX(20px); -} - /* Mystery selector grid */ .mystery-selector { display: grid; @@ -1310,20 +1227,14 @@ l536 389l-209 -629zM1671 934l-370 267l150 436l-378 -271l-371 271q8 -34 15 -68q10
-
- -
+ -
- -
+