From f243bfe89affb31568bd71e208133faf873fb163 Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Sat, 18 Jul 2026 17:28:42 +0200 Subject: [PATCH] feat(ui): elegant wedding white/silver/gold redesign MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reskin the whole app via design tokens in tailwind-theme.css (remapped color ramps) plus a define-once component layer in lib/styles/components.css (.btn, .card, .input, .chip, .badge, .sheet, …). Buttons are muted/outlined gold rather than flat fills. Self-host Inter + Fraunces (woff2) under the existing font-src 'self' CSP. Restyle the shared components and the account, admin, host, join, recover and upload screens against the new tokens. Co-Authored-By: Claude Opus 4.8 --- frontend/src/app.css | 1 + frontend/src/app.html | 28 +- frontend/src/lib/components/BottomNav.svelte | 2 +- .../src/lib/components/ConfirmSheet.svelte | 7 +- .../src/lib/components/ContextSheet.svelte | 6 +- .../src/lib/components/FeedListCard.svelte | 282 ++++++++-------- .../src/lib/components/HashtagChips.svelte | 14 +- .../src/lib/components/LightboxModal.svelte | 4 +- frontend/src/lib/components/Modal.svelte | 4 +- .../src/lib/components/OnboardingGuide.svelte | 18 +- .../src/lib/components/UploadSheet.svelte | 14 +- frontend/src/lib/styles/components.css | 120 +++++++ frontend/src/routes/account/+page.svelte | 50 +-- frontend/src/routes/admin/+page.svelte | 78 ++--- frontend/src/routes/admin/login/+page.svelte | 4 +- frontend/src/routes/host/+page.svelte | 98 ++---- frontend/src/routes/join/+page.svelte | 302 ++++++++++-------- frontend/src/routes/recover/+page.svelte | 6 +- frontend/src/routes/upload/+page.svelte | 45 ++- frontend/src/tailwind-theme.css | 158 +++++++-- frontend/static/fonts/Fraunces.woff2 | Bin 0 -> 67304 bytes frontend/static/fonts/Inter.woff2 | Bin 0 -> 48256 bytes 22 files changed, 696 insertions(+), 545 deletions(-) create mode 100644 frontend/src/lib/styles/components.css create mode 100644 frontend/static/fonts/Fraunces.woff2 create mode 100644 frontend/static/fonts/Inter.woff2 diff --git a/frontend/src/app.css b/frontend/src/app.css index d2e8f8f..db99611 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -1,4 +1,5 @@ @import './tailwind-theme.css'; +@import './lib/styles/components.css'; /* Respect the OS "reduce motion" setting. Collapses every animation/transition * (HeartBurst, Skeleton pulse, diashow cross-fades, sheet/FAB slides) to a diff --git a/frontend/src/app.html b/frontend/src/app.html index 7603fb7..157f701 100644 --- a/frontend/src/app.html +++ b/frontend/src/app.html @@ -7,8 +7,8 @@ - - + + @@ -61,31 +61,29 @@ align-items: center; justify-content: center; gap: 0.75rem; - background: #f9fafb; + background: #faf9f7; } html.dark #app-boot { - background: #030712; + background: #100f0f; } .app-boot__spinner { width: 2rem; height: 2rem; border-radius: 9999px; - border: 2px solid #d1d5db; - border-top-color: #2563eb; + border: 2px solid #e5e4e1; + border-top-color: #8a6a2b; animation: app-boot-spin 0.6s linear infinite; } html.dark .app-boot__spinner { - border-color: #374151; - border-top-color: #60a5fa; + border-color: #3b3a38; + border-top-color: #c6a24a; } .app-boot__label { - font-family: - system-ui, - -apple-system, - sans-serif; - font-size: 0.875rem; - font-weight: 500; - color: #9ca3af; + font-family: Georgia, 'Times New Roman', serif; + font-size: 1rem; + font-weight: 600; + letter-spacing: 0.01em; + color: #8a6a2b; } @keyframes app-boot-spin { to { diff --git a/frontend/src/lib/components/BottomNav.svelte b/frontend/src/lib/components/BottomNav.svelte index 72f3b1f..baf2fae 100644 --- a/frontend/src/lib/components/BottomNav.svelte +++ b/frontend/src/lib/components/BottomNav.svelte @@ -49,7 +49,7 @@
diff --git a/frontend/src/lib/components/ContextSheet.svelte b/frontend/src/lib/components/ContextSheet.svelte index 471a4c0..b97d397 100644 --- a/frontend/src/lib/components/ContextSheet.svelte +++ b/frontend/src/lib/components/ContextSheet.svelte @@ -147,11 +147,7 @@ {/each} -
diff --git a/frontend/src/lib/components/FeedListCard.svelte b/frontend/src/lib/components/FeedListCard.svelte index 142e8a4..a230662 100644 --- a/frontend/src/lib/components/FeedListCard.svelte +++ b/frontend/src/lib/components/FeedListCard.svelte @@ -66,170 +66,168 @@ -
- -
-
-
+
+ +
+
+
- {initials(upload.uploader_name)} -
-
-

- {upload.uploader_name} -

-

{relTime}

+ > + {initials(upload.uploader_name)} +
+
+

+ {upload.uploader_name} +

+

{relTime}

+
+ + {#if oncontextmenu} + + + {/if}
- {#if oncontextmenu} - - - {/if} -
- - - + + +
+
- {/if} - - - -
- - - {#if isOwn} - Eigener Beitrag + + + + {upload.comment_count} + + {#if isOwn} + Eigener Beitrag + {/if} +
+ + + {#if upload.caption} +

+ {upload.caption} +

{/if}
- - - {#if upload.caption} -

- {upload.caption} -

- {/if} - -
diff --git a/frontend/src/lib/components/HashtagChips.svelte b/frontend/src/lib/components/HashtagChips.svelte index e9b0780..c9a9347 100644 --- a/frontend/src/lib/components/HashtagChips.svelte +++ b/frontend/src/lib/components/HashtagChips.svelte @@ -18,10 +18,9 @@ @@ -29,10 +28,9 @@ diff --git a/frontend/src/lib/components/Modal.svelte b/frontend/src/lib/components/Modal.svelte index cb85abf..031ed59 100644 --- a/frontend/src/lib/components/Modal.svelte +++ b/frontend/src/lib/components/Modal.svelte @@ -49,9 +49,7 @@ use:focusTrap={{ onclose: onClose }} use:scrollLock > -
+
{@render children()}
diff --git a/frontend/src/lib/components/OnboardingGuide.svelte b/frontend/src/lib/components/OnboardingGuide.svelte index 093face..9a5ee7e 100644 --- a/frontend/src/lib/components/OnboardingGuide.svelte +++ b/frontend/src/lib/components/OnboardingGuide.svelte @@ -130,8 +130,17 @@
-
{currentStep.icon}
-

+
+
+ {currentStep.icon} +
+
+

{currentStep.title}

@@ -193,10 +202,7 @@ > Überspringen -
diff --git a/frontend/src/lib/components/UploadSheet.svelte b/frontend/src/lib/components/UploadSheet.svelte index d6564dd..1624d39 100644 --- a/frontend/src/lib/components/UploadSheet.svelte +++ b/frontend/src/lib/components/UploadSheet.svelte @@ -167,12 +167,7 @@ liken und kommentieren.

- + {:else} + {/if} diff --git a/frontend/src/lib/styles/components.css b/frontend/src/lib/styles/components.css new file mode 100644 index 0000000..3ec55fe --- /dev/null +++ b/frontend/src/lib/styles/components.css @@ -0,0 +1,120 @@ +/* ───────────────────────────────────────────────────────────────────────── + * EventSnap component layer — the shared, "define-once" building blocks. + * + * Colours/type/spacing tokens live in `tailwind-theme.css`; this file turns the + * *recurring UI patterns* (buttons, inputs, cards, badges, chips, sheets) into + * named classes so every page consumes the same look. Change a button here and + * it changes everywhere. + * + * These live in the `components` layer, which Tailwind emits BEFORE `utilities` + * — so a one-off inline utility (e.g. `rounded-lg`, `w-full`) on an element + * still overrides the component class. Reach for a component class first; drop + * to inline utilities only for genuinely one-off tweaks. + * ───────────────────────────────────────────────────────────────────────── */ + +@layer components { + /* ── Buttons ────────────────────────────────────────────────────────── + * Base + intent modifier (+ optional size). e.g. `class="btn btn-primary"`, + * `class="btn btn-secondary btn-sm"`, `class="btn btn-primary btn-block"`. */ + .btn { + @apply inline-flex select-none items-center justify-center gap-2 rounded-xl border border-transparent px-4 py-3 text-sm font-semibold transition; + @apply focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/40; + @apply active:scale-[0.99] disabled:cursor-not-allowed; + } + .btn-lg { + @apply px-5 py-3.5 text-base; + } + .btn-sm { + @apply rounded-lg px-3 py-2; + } + .btn-block { + @apply w-full; + } + + /* Primary = muted champagne fill + gold border + gold text (an elegant, + * outlined "signal" rather than an aggressive solid gold block). */ + .btn-primary { + @apply border-primary-400 bg-primary-100 text-primary-800 shadow-sm hover:border-primary-500 hover:bg-primary-200; + @apply disabled:border-gray-200 disabled:bg-gray-100 disabled:text-gray-400 disabled:shadow-none; + @apply dark:border-primary-500/50 dark:bg-primary-950/40 dark:text-primary-200 dark:hover:border-primary-500 dark:hover:bg-primary-900/40; + } + .btn-secondary { + @apply border border-gray-300 bg-white text-gray-700 hover:bg-gray-50 disabled:opacity-50; + @apply dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700; + } + .btn-ghost { + @apply text-gray-600 hover:bg-gray-100 hover:text-gray-900 disabled:opacity-50; + @apply dark:text-gray-300 dark:hover:bg-gray-800 dark:hover:text-gray-100; + } + .btn-danger { + @apply bg-red-600 text-white shadow-sm hover:bg-red-700 disabled:opacity-50; + @apply dark:bg-red-600 dark:hover:bg-red-500; + } + + /* ── Form inputs ────────────────────────────────────────────────────── + * Covers text/number inputs and textareas. */ + .input { + @apply w-full rounded-xl border border-gray-300 bg-white px-4 py-3 text-gray-900 placeholder-gray-400 transition; + @apply focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/25; + @apply dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:placeholder-gray-500; + } + + /* ── Surfaces ───────────────────────────────────────────────────────── + * `card` — the standard raised surface (page → card → surface-muted is the + * three-level elevation ramp). + * `surface-muted` — a nested/inset panel inside a card. */ + .card { + @apply rounded-2xl border border-gray-200/70 bg-white shadow-sm dark:border-gray-800 dark:bg-gray-900; + } + .surface-muted { + @apply rounded-xl bg-gray-50 dark:bg-gray-800/60; + } + + /* ── Badges (status / role pills) ───────────────────────────────────── + * `class="badge badge-gold"` etc. A leading dot is optional in markup. */ + .badge { + @apply inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-semibold; + } + .badge-primary { + @apply bg-primary-100 text-primary-700 dark:bg-primary-900/40 dark:text-primary-200; + } + .badge-gold { + @apply bg-purple-100 text-purple-800 dark:bg-purple-900/40 dark:text-purple-200; + } + .badge-gray { + @apply bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-300; + } + .badge-success { + @apply bg-green-100 text-green-700 dark:bg-green-950/50 dark:text-green-300; + } + .badge-danger { + @apply bg-red-100 text-red-700 dark:bg-red-950/50 dark:text-red-300; + } + + /* ── Chips (filter / toggle) ────────────────────────────────────────── + * `class="chip chip-active"` / `class="chip chip-inactive"`. */ + .chip { + @apply rounded-full border border-transparent px-4 py-2 text-sm font-medium transition; + } + .chip-inactive { + @apply bg-gray-100 text-gray-600 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700; + } + /* Active = gold outline + soft champagne fill (matches .btn-primary). */ + .chip-active { + @apply border-primary-400 bg-primary-100 text-primary-800 dark:border-primary-500/50 dark:bg-primary-950/40 dark:text-primary-200; + } + + /* ── Bottom-sheet surface ───────────────────────────────────────────── + * The rounded top panel shared by upload / context / confirm sheets. */ + .sheet { + @apply rounded-t-3xl bg-white p-6 shadow-2xl dark:bg-gray-900 sm:rounded-2xl; + } + + /* ── Page scaffold + section heading ──────────────────────────────────*/ + .page { + @apply min-h-screen bg-gray-50 dark:bg-gray-950; + } + .section-title { + @apply font-display text-lg font-semibold text-gray-900 dark:text-gray-100; + } +} diff --git a/frontend/src/routes/account/+page.svelte b/frontend/src/routes/account/+page.svelte index 8570d84..eceb89e 100644 --- a/frontend/src/routes/account/+page.svelte +++ b/frontend/src/routes/account/+page.svelte @@ -163,9 +163,7 @@
-
+
+

-

Wiederherstellungs-PIN

-

+

+ Wiederherstellungs-PIN +

+

Du brauchst diesen PIN, um dein Konto auf einem anderen Gerät wiederherzustellen. Schreib ihn auf!

@@ -287,7 +285,7 @@ > @@ -337,9 +335,7 @@ -
+

Design @@ -394,9 +390,7 @@

-
+

Datennutzung @@ -439,9 +433,7 @@ {#if $quotaStore.enabled && $quotaStore.limit_bytes != null} -
+

@@ -472,9 +464,7 @@ {#if $privacyNote.trim()} -
+

@@ -486,9 +476,7 @@ {/if} -
+

Konto @@ -611,16 +599,10 @@

Original-Dateien können deutlich mehr Datenvolumen verbrauchen. Am besten im WLAN aktivieren.

- -

diff --git a/frontend/src/routes/admin/+page.svelte b/frontend/src/routes/admin/+page.svelte index 5eae3d8..dd0b013 100644 --- a/frontend/src/routes/admin/+page.svelte +++ b/frontend/src/routes/admin/+page.svelte @@ -453,10 +453,7 @@ Kopieren
- {/if} @@ -473,16 +470,10 @@ Diashow und Export, und die Sitzung wird beendet. Rückgängig machbar über „Entsperren“.

- -
@@ -543,33 +534,25 @@
{#if stats}
-
+

{stats.user_count}

Gäste

-
+

{stats.upload_count}

Uploads

-
+

{stats.comment_count}

Kommentare

-
+

{diskPct(stats)} %

@@ -577,9 +560,7 @@
-
+
@@ -611,9 +592,7 @@ {:else if activeTab === 'config'}
{#each CONFIG_GROUPS as group (group.title)} -
+

{#if field.hint}

{field.hint}

@@ -670,7 +649,7 @@ min="0" inputmode="decimal" bind:value={configDraft[field.key]} - class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-200 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100" + class="input text-sm" /> {#if field.hint}

{field.hint}

@@ -686,11 +665,7 @@
-
@@ -700,9 +675,7 @@ {:else if activeTab === 'export'}
-
+

Galerie

-
+

Export-Jobs

diff --git a/frontend/src/routes/host/+page.svelte b/frontend/src/routes/host/+page.svelte index 2ca962d..a310398 100644 --- a/frontend/src/routes/host/+page.svelte +++ b/frontend/src/routes/host/+page.svelte @@ -437,12 +437,7 @@ Kopieren
- + {/if} @@ -458,17 +453,10 @@ ansehen, Keepsake herunterladen) bleibt bestehen. Rückgängig machbar über „Entsperren“.

- -
@@ -551,15 +539,13 @@ {/if} -
+
-
+
@@ -751,15 +734,13 @@
-
+

diff --git a/frontend/src/routes/join/+page.svelte b/frontend/src/routes/join/+page.svelte index 99aedbb..f729f14 100644 --- a/frontend/src/routes/join/+page.svelte +++ b/frontend/src/routes/join/+page.svelte @@ -139,142 +139,184 @@ } -

-
- {#if nameTaken} - +
+ + + + +
+ +
-

- „{takenName}" ist bereits vergeben. -

-

- Wähle einen anderen Namen, z. B. einen Spitznamen oder füge deinen Nachnamen hinzu („{takenName} - M." oder „{takenName} aus Berlin"). -

+
- -

- Falls du das bist, melde dich mit deinem PIN an: -

- -
{ - e.preventDefault(); - handleInlineRecover(); - }} + EventSnap - +
- {#if recoveryError} -

- {recoveryError} + +

+ {#if nameTaken} + +
+

+ „{takenName}" ist bereits vergeben.

- {/if} +

+ Wähle einen anderen Namen, z. B. einen Spitznamen oder füge deinen Nachnamen hinzu + („{takenName} + M." oder „{takenName} aus Berlin"). +

+
+ +

+ Falls du das bist, melde dich mit deinem PIN an: +

+ + { + e.preventDefault(); + handleInlineRecover(); + }} + > + + + {#if recoveryError} +

+ {recoveryError} +

+ {/if} + + + - - - - - {#if pinRequestSent} -

- Anfrage gesendet. Bitte einen Host, deine PIN zurückzusetzen — danach kannst du dich mit - der neuen PIN anmelden. -

+ + {#if pinRequestSent} +

+ Anfrage gesendet. Bitte einen Host, deine PIN zurückzusetzen — danach kannst du dich mit + der neuen PIN anmelden. +

+ {:else} + + {/if} {:else} - - {/if} - {:else} - -

- Willkommen! -

- {#if eventName} -

- {eventName} + + + {#if error} +

+ {error} +

+ {/if} + + + + +

+ Ich habe bereits einen Account

{/if} -

- Gib deinen Namen ein, um dem Event beizutreten. -

- -
{ - e.preventDefault(); - handleJoin(); - }} - > - - - {#if error} -

- {error} -

- {/if} - - -
- -

- Ich habe bereits einen Account -

- {/if} +
@@ -284,7 +326,7 @@ data-testid="pin-modal" >