From b42db508a357e3cceb6f6ba3a5b64dd7c568e9d8 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Fri, 12 Dec 2025 02:37:43 +0100 Subject: [PATCH] feat(calendar): improve calendar UI with new components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update CalendarHeader with better navigation - Add PillCalendarSelector for calendar switching - Improve DateStrip with view range highlighting - Update CalendarToolbar with refined controls - Remove separate event/new page (using modal instead) - Adjust app.css for new layout 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- apps/calendar/apps/web/src/app.css | 58 +-- .../components/calendar/CalendarHeader.svelte | 318 +------------- .../calendar/CalendarToolbar.svelte | 6 + .../lib/components/calendar/DateStrip.svelte | 78 ++-- .../calendar/PillCalendarSelector.svelte | 412 ++++++++++++++++++ .../apps/web/src/routes/(app)/+page.svelte | 54 +-- .../src/routes/(app)/event/new/+page.svelte | 79 ---- 7 files changed, 495 insertions(+), 510 deletions(-) create mode 100644 apps/calendar/apps/web/src/lib/components/calendar/PillCalendarSelector.svelte delete mode 100644 apps/calendar/apps/web/src/routes/(app)/event/new/+page.svelte diff --git a/apps/calendar/apps/web/src/app.css b/apps/calendar/apps/web/src/app.css index d625b6bc8..558ec4ab5 100644 --- a/apps/calendar/apps/web/src/app.css +++ b/apps/calendar/apps/web/src/app.css @@ -42,18 +42,18 @@ /* Hour slot in day/week view */ .hour-slot { height: var(--hour-height); - border-bottom: 1px solid hsl(var(--color-border) / 0.5); + border-bottom: 1px solid color-mix(in srgb, var(--color-border) 50%, transparent); position: relative; } .hour-slot:hover { - background-color: hsl(var(--color-muted) / 0.3); + background-color: color-mix(in srgb, var(--color-muted) 30%, transparent); } /* Event card in calendar */ .event-card { - background-color: hsl(var(--color-primary)); - color: hsl(var(--color-primary-foreground)); + background-color: var(--color-primary); + color: var(--color-primary-foreground); border-radius: var(--radius-sm); padding: 2px 6px; font-size: 0.75rem; @@ -70,17 +70,17 @@ /* Day cell in month view */ .day-cell { min-height: 100px; - border: 1px solid hsl(var(--color-border)); + border: 1px solid var(--color-border); padding: var(--spacing-xs); transition: background-color var(--transition-fast); } .day-cell:hover { - background-color: hsl(var(--color-muted) / 0.3); + background-color: color-mix(in srgb, var(--color-muted) 30%, transparent); } .day-cell.today { - background-color: hsl(var(--color-primary) / 0.1); + background-color: color-mix(in srgb, var(--color-primary) 10%, transparent); } .day-cell.other-month { @@ -93,7 +93,7 @@ left: 0; right: 0; height: 2px; - background-color: hsl(var(--color-error)); + background-color: var(--color-error); z-index: 10; } @@ -105,7 +105,7 @@ width: 10px; height: 10px; border-radius: 50%; - background-color: hsl(var(--color-error)); + background-color: var(--color-error); } /* Mini calendar */ @@ -125,24 +125,24 @@ } .mini-calendar .day:hover { - background-color: hsl(var(--color-muted)); + background-color: var(--color-muted); } .mini-calendar .day.today { - background-color: hsl(var(--color-primary)); - color: hsl(var(--color-primary-foreground)); + background-color: var(--color-primary); + color: var(--color-primary-foreground); } .mini-calendar .day.selected { - border: 2px solid hsl(var(--color-primary)); + border: 2px solid var(--color-primary); } /* Card styles */ .card { - background-color: hsl(var(--color-surface)); + background-color: var(--color-surface); border-radius: var(--radius-lg); padding: var(--spacing-lg); - border: 1px solid hsl(var(--color-border)); + border: 1px solid var(--color-border); } /* Button styles */ @@ -161,12 +161,12 @@ } .btn-primary { - background: hsl(var(--color-primary)); - color: hsl(var(--color-primary-foreground)); + background: var(--color-primary); + color: var(--color-primary-foreground); } .btn-primary:hover { - background: hsl(var(--color-primary) / 0.9); + filter: brightness(0.9); } .btn-primary:disabled { @@ -175,21 +175,21 @@ } .btn-secondary { - background: hsl(var(--color-secondary)); - color: hsl(var(--color-secondary-foreground)); + background: var(--color-secondary); + color: var(--color-secondary-foreground); } .btn-secondary:hover { - background: hsl(var(--color-secondary) / 0.8); + filter: brightness(0.9); } .btn-ghost { background: transparent; - color: hsl(var(--color-foreground)); + color: var(--color-foreground); } .btn-ghost:hover { - background: hsl(var(--color-muted)); + background: var(--color-muted); } .btn-icon { @@ -206,21 +206,21 @@ display: block; width: 100%; padding: 0.5rem 0.75rem; - border: 2px solid hsl(var(--color-border)); + border: 2px solid var(--color-border); border-radius: var(--radius-md); - background-color: hsl(var(--color-background)); - color: hsl(var(--color-foreground)); + background-color: var(--color-background); + color: var(--color-foreground); font-size: 0.875rem; transition: border-color var(--transition-fast); } .input:focus { outline: none; - border-color: hsl(var(--color-primary)); + border-color: var(--color-primary); } .input::placeholder { - color: hsl(var(--color-muted-foreground)); + color: var(--color-muted-foreground); } /* Select styling */ @@ -235,7 +235,7 @@ select.input { /* Text colors */ .text-destructive { - color: hsl(var(--color-error)); + color: var(--color-error); } /* Scrollbar styling */ diff --git a/apps/calendar/apps/web/src/lib/components/calendar/CalendarHeader.svelte b/apps/calendar/apps/web/src/lib/components/calendar/CalendarHeader.svelte index 81a8ac396..b16235177 100644 --- a/apps/calendar/apps/web/src/lib/components/calendar/CalendarHeader.svelte +++ b/apps/calendar/apps/web/src/lib/components/calendar/CalendarHeader.svelte @@ -1,50 +1,7 @@ -
-
- - - - -

{title}

-
- -
- -
- - - - - - - - -
- - - -
+
+

{title}

diff --git a/apps/calendar/apps/web/src/lib/components/calendar/CalendarToolbar.svelte b/apps/calendar/apps/web/src/lib/components/calendar/CalendarToolbar.svelte index 658bfd49f..42ab7806d 100644 --- a/apps/calendar/apps/web/src/lib/components/calendar/CalendarToolbar.svelte +++ b/apps/calendar/apps/web/src/lib/components/calendar/CalendarToolbar.svelte @@ -9,6 +9,7 @@ PillTimeRangeSelector, PillViewSwitcher, } from '@manacore/shared-ui'; + import PillCalendarSelector from './PillCalendarSelector.svelte'; // View type labels const viewLabels: Record = { @@ -55,6 +56,11 @@ + + + + + viewStore.goToToday()} title="Zum heutigen Tag springen"> Heute diff --git a/apps/calendar/apps/web/src/lib/components/calendar/DateStrip.svelte b/apps/calendar/apps/web/src/lib/components/calendar/DateStrip.svelte index 413c58e47..06cf4c413 100644 --- a/apps/calendar/apps/web/src/lib/components/calendar/DateStrip.svelte +++ b/apps/calendar/apps/web/src/lib/components/calendar/DateStrip.svelte @@ -120,6 +120,7 @@ if (!scrollContainer || isLoadingMore) return; checkTodayVisibility(); + updateVisibleMonth(); const { scrollLeft, clientWidth } = scrollContainer; const dayWidth = 54; @@ -135,14 +136,28 @@ } } - function getMonthLabel(day: Date, index: number): string | null { - if (day.getDate() === 1 || index === 0) { - if (day.getMonth() === 0 && day.getDate() === 1) { - return format(day, 'MMM yyyy', { locale: de }); + // Get the month of the center visible day + let visibleMonth = $state(format(new Date(), 'MMMM yyyy', { locale: de })); + + function updateVisibleMonth() { + if (!scrollContainer) return; + + const containerRect = scrollContainer.getBoundingClientRect(); + const centerX = containerRect.left + containerRect.width / 2; + + // Find the day element closest to center + const dayElements = scrollContainer.querySelectorAll('.day-item'); + for (const el of dayElements) { + const rect = el.getBoundingClientRect(); + if (rect.left <= centerX && rect.right >= centerX) { + const dateStr = el.getAttribute('data-date'); + if (dateStr) { + const date = new Date(dateStr); + visibleMonth = format(date, 'MMMM yyyy', { locale: de }); + } + break; } - return format(day, 'MMM', { locale: de }); } - return null; } onMount(() => { @@ -156,20 +171,20 @@ {/if}
+ +
+ {visibleMonth} +
+ +
- {#each days as day, index} - {@const monthLabel = getMonthLabel(day, index)} + {#each days as day} {@const dayIsToday = isToday(day)} {@const dayIsSelected = isSameDay(day, currentDate)} {@const dayIsWeekend = day.getDay() === 0 || day.getDay() === 6} {@const dayInRange = isWithinInterval(day, { start: viewRange.start, end: viewRange.end })} {@const dayIsRangeStart = isSameDay(day, viewRange.start)} {@const dayIsRangeEnd = isSameDay(day, viewRange.end)} - {#if monthLabel} -
- {monthLabel} -
- {/if} + + {#if isOpen} + + + + + + {/if} +
+ + diff --git a/apps/calendar/apps/web/src/routes/(app)/+page.svelte b/apps/calendar/apps/web/src/routes/(app)/+page.svelte index 73373d0d3..446464bc3 100644 --- a/apps/calendar/apps/web/src/routes/(app)/+page.svelte +++ b/apps/calendar/apps/web/src/routes/(app)/+page.svelte @@ -1,7 +1,6 @@ @@ -133,20 +121,6 @@ - - - - - - @@ -167,23 +141,11 @@ /> -
{/if}
- -
{#if !initialized} @@ -317,8 +279,7 @@ } } - .fab-expand, - .fab-new-event { + .fab-expand { width: 48px; height: 48px; border-radius: var(--radius-full); @@ -329,9 +290,6 @@ cursor: pointer; transition: all 150ms ease; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); - } - - .fab-expand { background: hsl(var(--color-surface)); color: hsl(var(--color-foreground)); border: 1px solid hsl(var(--color-border)); @@ -342,16 +300,6 @@ transform: scale(1.05); } - .fab-new-event { - background: hsl(var(--color-primary)); - color: hsl(var(--color-primary-foreground)); - } - - .fab-new-event:hover { - background: hsl(var(--color-primary) / 0.9); - transform: scale(1.05); - } - .calendar-main { flex: 1; display: flex; diff --git a/apps/calendar/apps/web/src/routes/(app)/event/new/+page.svelte b/apps/calendar/apps/web/src/routes/(app)/event/new/+page.svelte deleted file mode 100644 index fb375c300..000000000 --- a/apps/calendar/apps/web/src/routes/(app)/event/new/+page.svelte +++ /dev/null @@ -1,79 +0,0 @@ - - - - Neuer Termin | Kalender - - -
-
-

Neuer Termin

- -
-
- -