refactor(calendar): EventDateBox-Komponente für Datums-Kachel
Deploy / verify (push) Successful in 1m7s
Deploy / deploy (push) Successful in 1m59s

Einzel- und Mehrtages-Datum in eine dedizierte Komponente ausgelagert.
Beide Varianten gleiche Höhe (h-20); Mehrtag zeigt Wochentag- und Tag-Range
(z. B. "Sa–So" / "27–28") und wächst nur in der Breite. Zentriert gestapelt
(kein Overflow), himmel-Box konsistent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Peter Meier
2026-06-20 14:00:54 +02:00
parent 6925ffee45
commit 905c2e4d36
3 changed files with 59 additions and 56 deletions
+8 -53
View File
@@ -18,6 +18,7 @@
import ImageModal from "$lib/components/ImageModal.svelte";
import SocialImageModal from "$lib/components/SocialImageModal.svelte";
import QrModal from "$lib/components/QrModal.svelte";
import EventDateBox from "./EventDateBox.svelte";
type EventCardItem = CalendarItemData & {
start: Date;
@@ -604,59 +605,13 @@
<summary
class="cursor-pointer list-none p-3 flex items-start gap-3 hover:bg-himmel-50/60 focus-visible:outline focus-visible:outline-2 focus-visible:outline-himmel-500"
>
<!-- Datum-Block: Wochentag/Tag/Monat in vertikalem Stack —
als Block scannbar, große Tag-Zahl als Anker. Bei Multi-
Day fällt das Block-Layout auf Range zurück. -->
{#if item.isMultiDay && item.end}
<div
class="event-date-range shrink-0 w-20 text-center leading-tight"
>
<div
class="text-[10px] uppercase tracking-wide text-stein-500"
>
{item.start.toLocaleDateString("de-DE", {
month: "short",
})}
</div>
<div
class="text-base font-bold text-stein-900 tabular-nums"
>
{item.start.getDate()}{item.end.getDate()}
</div>
<div class="text-[10px] text-stein-500">
{item.start.getFullYear() ===
item.end.getFullYear()
? item.end.toLocaleDateString("de-DE", {
month: "short",
})
: item.end.getFullYear()}
</div>
</div>
{:else}
<div
class="event-date-block shrink-0 w-14 aspect-square flex flex-col items-center justify-between leading-tight bg-himmel-800 rounded-xs py-2"
>
<div
class="text-[10px] uppercase tracking-wide text-himmel-300"
>
{item.start.toLocaleDateString("de-DE", {
weekday: "short",
})}
</div>
<div
class="text-2xl font-bold text-himmel-50 tabular-nums"
>
{item.start.getDate()}
</div>
<div
class="text-[10px] uppercase tracking-wide text-himmel-300"
>
{item.start.toLocaleDateString("de-DE", {
month: "short",
})}
</div>
</div>
{/if}
<!-- Datum-Kachel: Wochentag/Tag/Monat (Einzel) bzw.
Wochentag- und Tag-Range (mehrtägig). -->
<EventDateBox
start={item.start}
end={item.end}
multiDay={!!item.isMultiDay}
/>
<div class="flex-1 min-w-0">
<div class="flex items-baseline gap-2 flex-wrap">
<span
@@ -0,0 +1,45 @@
<script lang="ts">
/**
* Datum-Kachel für Kalender-Einträge: himmel-Box mit Wochentag/Tag/Monat.
* Einzeltermin → großer Tag. Mehrtägig → Wochentag- und Tag-Range (z. B.
* "SaSo" / "2728"). Beide Varianten haben dieselbe Höhe; die Box wächst
* für Ranges nur in der Breite (min-w-14 + px), bleibt also konsistent.
*/
let {
start,
end = null,
multiDay = false,
}: { start: Date; end?: Date | null; multiDay?: boolean } = $props();
const wd = (d: Date) =>
d.toLocaleDateString("de-DE", { weekday: "short" }).replace(/\.$/, "");
const mon = (d: Date) => d.toLocaleDateString("de-DE", { month: "short" });
const isRange = $derived(multiDay && !!end);
</script>
<div
class="event-date-box shrink-0 h-20 min-w-20 px-2.5 flex flex-col items-center justify-center gap-1 overflow-hidden leading-none bg-himmel-800 rounded-sm"
>
{#if isRange && end}
<div class="text-[11px] uppercase tracking-wide text-himmel-300 whitespace-nowrap">
{wd(start)}{wd(end)}
</div>
<div class="text-lg font-bold tracking-tight text-himmel-50 tabular-nums whitespace-nowrap">
{start.getDate()}{end.getDate()}
</div>
<div class="text-[11px] uppercase tracking-wide text-himmel-300">
{mon(start)}
</div>
{:else}
<div class="text-[11px] uppercase tracking-wide text-himmel-300">
{wd(start)}
</div>
<div class="text-3xl font-bold text-himmel-50 tabular-nums">
{start.getDate()}
</div>
<div class="text-[11px] uppercase tracking-wide text-himmel-300">
{mon(start)}
</div>
{/if}
</div>
+6 -3
View File
@@ -123,6 +123,9 @@
"magnify-plus": {
"body": "<path fill=\"currentColor\" d=\"M9 2a7 7 0 0 1 7 7c0 1.57-.5 3-1.39 4.19l.8.81H16l6 6l-2 2l-6-6v-.59l-.81-.8A6.9 6.9 0 0 1 9 16a7 7 0 0 1-7-7a7 7 0 0 1 7-7M8 5v3H5v2h3v3h2v-3h3V8h-3V5z\"/>"
},
"arrow-right": {
"body": "<path fill=\"currentColor\" d=\"M4 11v2h12l-5.5 5.5l1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5L16 11z\"/>"
},
"file-download": {
"body": "<path fill=\"currentColor\" d=\"M14 2H6c-1.11 0-2 .89-2 2v16c0 1.11.89 2 2 2h12c1.11 0 2-.89 2-2V8zm-2 17l-4-4h2.5v-3h3v3H16zm1-10V3.5L18.5 9z\"/>"
},
@@ -138,9 +141,6 @@
"calendar-month-outline": {
"body": "<path fill=\"currentColor\" d=\"M7 11h2v2H7zm14-6v14c0 1.11-.89 2-2 2H5a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2h1V1h2v2h8V1h2v2h1a2 2 0 0 1 2 2M5 7h14V5H5zm14 12V9H5v10zm-4-6v-2h2v2zm-4 0v-2h2v2zm-4 2h2v2H7zm8 2v-2h2v2zm-4 0v-2h2v2z\"/>"
},
"arrow-right": {
"body": "<path fill=\"currentColor\" d=\"M4 11v2h12l-5.5 5.5l1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5L16 11z\"/>"
},
"download-outline": {
"body": "<path fill=\"currentColor\" d=\"M13 5v6h1.17L12 13.17L9.83 11H11V5zm2-2H9v6H5l7 7l7-7h-4zm4 15H5v2h14z\"/>"
},
@@ -228,6 +228,9 @@
"home-outline": {
"body": "<path fill=\"currentColor\" d=\"m12 5.69l5 4.5V18h-2v-6H9v6H7v-7.81zM12 3L2 12h3v8h6v-6h2v6h6v-8h3\"/>"
},
"calendar-month": {
"body": "<path fill=\"currentColor\" d=\"M9 10v2H7v-2zm4 0v2h-2v-2zm4 0v2h-2v-2zm2-7a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h1V1h2v2h8V1h2v2zm0 16V8H5v11zM9 14v2H7v-2zm4 0v2h-2v-2zm4 0v2h-2v-2z\"/>"
},
"share-variant-outline": {
"body": "<path fill=\"currentColor\" d=\"M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81c1.66 0 3-1.34 3-3s-1.34-3-3-3s-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66c0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91s-1.31-2.92-2.92-2.92M18 4c.55 0 1 .45 1 1s-.45 1-1 1s-1-.45-1-1s.45-1 1-1M6 13c-.55 0-1-.45-1-1s.45-1 1-1s1 .45 1 1s-.45 1-1 1m12 7c-.55 0-1-.45-1-1s.45-1 1-1s1 .45 1 1s-.45 1-1 1\"/>"
},