refactor: complete Svelte 5 migration to eliminate all deprecation warnings
All checks were successful
CI / update (push) Successful in 1m35s

Migrated all components and routes to Svelte 5 syntax standards:

Event Handlers:
- Updated all deprecated on:* directives to new on* attribute syntax
- Changed on:click → onclick, on:keydown → onkeydown, on:input → oninput
- Updated on:blur, on:focus, on:load, on:submit, on:cancel handlers

Reactive State:
- Added $state() declarations for all reactive variables
- Fixed non-reactive update warnings in layout and component files

Component API:
- Replaced <slot /> with {@render children()} pattern
- Added children prop to components using slots

Accessibility:
- Added id attributes to inputs and for attributes to labels
- Fixed label-control associations across forms
- Removed event listeners from non-interactive elements

HTML Fixes:
- Fixed self-closing textarea tags
- Corrected implicitly closed elements
- Proper element nesting

CSS Cleanup:
- Removed 20+ unused CSS selectors across components
- Cleaned up orphaned styles from refactoring

All vite-plugin-svelte warnings resolved. Codebase now fully compliant with Svelte 5.
This commit is contained in:
2026-01-05 23:39:33 +01:00
parent 2de51ee492
commit f66334290a
21 changed files with 120 additions and 259 deletions

View File

@@ -1,7 +1,5 @@
<script>
let { children } = $props();
</script>
<slot />
<style>
</style>
{@render children()}

View File

@@ -499,8 +499,9 @@ button.action_button{
<p style="margin: 0 0 0.5rem 0; font-size: 0.9rem; color: var(--nord3);"><strong>Bild {i + 1}:</strong> {image.mediapath}</p>
<div style="margin-bottom: 0.75rem;">
<label style="display: block; margin-bottom: 0.25rem; font-weight: bold; font-size: 0.9rem;">Alt-Text (DE):</label>
<label for="image-alt-{i}" style="display: block; margin-bottom: 0.25rem; font-weight: bold; font-size: 0.9rem;">Alt-Text (DE):</label>
<input
id="image-alt-{i}"
type="text"
bind:value={image.alt}
placeholder="Beschreibung des Bildes für Screenreader (Deutsch)"
@@ -509,8 +510,9 @@ button.action_button{
</div>
<div style="margin-bottom: 0.75rem;">
<label style="display: block; margin-bottom: 0.25rem; font-weight: bold; font-size: 0.9rem;">Caption (DE):</label>
<label for="image-caption-{i}" style="display: block; margin-bottom: 0.25rem; font-weight: bold; font-size: 0.9rem;">Caption (DE):</label>
<input
id="image-caption-{i}"
type="text"
bind:value={image.caption}
placeholder="Bildunterschrift (optional)"

View File

@@ -9,14 +9,10 @@
import UserHeader from '$lib/components/UserHeader.svelte';
let { data, children } = $props();
let showModal = false;
let paymentId = null;
let user;
if (data.session) {
user = data.session.user;
}
let showModal = $state(false);
let paymentId = $state(null);
let user = $state(data.session?.user);
$effect(() => {
// Check if URL contains payment view route OR if we have paymentId in state

View File

@@ -317,10 +317,6 @@
color: var(--red);
}
.even {
color: var(--nord3);
}
.actions {
display: flex;
gap: 1rem;
@@ -617,16 +613,6 @@
}
}
.you-badge {
background-color: var(--blue);
color: white;
padding: 0.125rem 0.5rem;
border-radius: 1rem;
font-size: 0.75rem;
font-weight: 500;
display: inline-block;
}
.activity-amount {
font-weight: bold;
font-size: 1rem;
@@ -645,7 +631,7 @@
flex-wrap: wrap;
}
.paid-by, .payment-date {
.payment-date {
color: var(--nord3);
font-size: 0.9rem;
}
@@ -659,7 +645,7 @@
}
@media (prefers-color-scheme: dark) {
.paid-by, .payment-date {
.payment-date {
color: var(--nord4);
}

View File

@@ -803,18 +803,10 @@
display: block;
}
.js-enhanced {
display: none;
}
:global(body.js-loaded) .no-js-only {
display: none;
}
:global(body.js-loaded) .js-enhanced {
display: block;
}
.manual-users textarea {
width: 100%;
padding: 0.75rem;

View File

@@ -463,32 +463,6 @@
gap: 2rem;
}
.form-section {
background: var(--nord6);
padding: 1.5rem;
border-radius: 0.75rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border: 1px solid var(--nord4);
}
.form-section h2 {
margin-top: 0;
margin-bottom: 1rem;
color: var(--nord0);
font-size: 1.25rem;
}
@media (prefers-color-scheme: dark) {
.form-section {
background: var(--nord1);
border-color: var(--nord2);
}
.form-section h2 {
color: var(--font-default-dark);
}
}
.form-group {
margin-bottom: 1rem;
}

View File

@@ -479,15 +479,6 @@
margin-left: 0;
}
.header-content {
flex-direction: column;
align-items: stretch;
}
.header-actions {
justify-content: center;
}
.info-grid {
grid-template-columns: 1fr;
}

View File

@@ -794,18 +794,6 @@ onMount(() => {
font-size: 1.3rem;
}
.prayer-text {
font-size: 1.15rem;
line-height: 1.8;
color: var(--nord4);
}
@media(prefers-color-scheme: light) {
.prayer-text {
color: var(--nord0);
}
}
/* Prayer component bilingual styling */
.prayer-section :global(p) {
text-align: center;
@@ -1045,21 +1033,6 @@ h1 {
}
/* Mystery description styling */
.mystery-description {
margin: 1.5rem 0 1.5rem 0;
display: flex;
flex-direction: column;
gap: 0.75rem;
align-items: center;
}
.mystery-title {
font-weight: 700;
color: var(--nord10);
font-size: 1.1rem;
text-align: center;
}
.decade-buttons {
display: flex;
flex-direction: row;
@@ -1533,8 +1506,7 @@ Die Integration der lichtreichen Geheimnisse hat einige Kontroversen um sich.
Ohne diese 5 Dekaden sind die 150 Gebete der drei Sätzen an Geheimnissen eine direkte Parallele zu den 150 Psalmen der Bibel.
Die Gottgegebenheit der lichtreichen Geheimnisse ist auch umstritten.
</p>
Der Plan ohne lichtreiche Geheimnisse ist wie folgt:
<p>
<p>Der Plan ohne lichtreiche Geheimnisse ist wie folgt:</p>
<div class=table>
<table>
<tbody>