From b16e4b8e67528f326013d4d6b86aed277288769d Mon Sep 17 00:00:00 2001 From: Schalli Date: Wed, 16 Sep 2026 13:54:34 +0200 Subject: [PATCH] fix(web): Kalender-Tooltip bricht lange Termintitel um (Breite/Klemmung aus einer Konstante) - Titel-Span im Tooltip: min-w-0 break-words statt truncate - Breite (288px) und Rand-Klemmung aus TOOLTIP_WIDTH_PX/TOOLTIP_EDGE_PX - Test 4c: belegt Klassen und Tooltip-Breite Co-Authored-By: Claude Opus 5 (1M context) --- .../widgets/calendar-widget.test.tsx | 29 +++++++++++++++++++ .../dashboard/widgets/calendar-widget.tsx | 22 ++++++++++---- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx b/apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx index b05b0d6..aa72430 100644 --- a/apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx +++ b/apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx @@ -200,6 +200,35 @@ describe('CalendarWidget', () => { expect(tooltip).not.toHaveTextContent('e6'); }); + it('Test 4c: Tooltip bricht lange Termintitel um statt sie abzuschneiden', async () => { + mockFetchEvents.mockResolvedValue([ + ev( + 'Deutscher Weltkindertag (Aktionstag der Kinderrechte)', + new Date(2026, 6, 20, 9, 0), + new Date(2026, 6, 20, 10, 0), + ), + ]); + + const { CalendarWidget } = await import('./calendar-widget'); + render(); + + await waitFor(() => { + expect(screen.getByText('Juli 2026')).toBeInTheDocument(); + }); + + const day20 = document.querySelector('[data-date="2026-07-20"]') as HTMLElement; + fireEvent.mouseEnter(day20); + + const tooltip = screen.getByTestId('calendar-day-tooltip'); + const title = within(tooltip).getByText( + 'Deutscher Weltkindertag (Aktionstag der Kinderrechte)', + ); + expect(title).toHaveClass('break-words'); + expect(title).toHaveClass('min-w-0'); + expect(title).not.toHaveClass('truncate'); + expect(tooltip).toHaveStyle({ width: '288px' }); + }); + it('Test 5: Naechste Termine respektiert maxEvents, Reihenfolge und zeigt Ort/Farbpunkt', async () => { mockFetchEvents.mockResolvedValue([ ev('E1', new Date(2026, 6, 16, 9, 0), new Date(2026, 6, 16, 10, 0)), diff --git a/apps/web/src/components/dashboard/widgets/calendar-widget.tsx b/apps/web/src/components/dashboard/widgets/calendar-widget.tsx index c5fc05f..9b3d181 100644 --- a/apps/web/src/components/dashboard/widgets/calendar-widget.tsx +++ b/apps/web/src/components/dashboard/widgets/calendar-widget.tsx @@ -18,6 +18,12 @@ import { WEEKDAY_LABELS, } from './calendar-month'; +// quick-260916-j4f: Breite und Rand-Klemmung des Termin-Tooltips aus einer +// Quelle, damit Breite und Klemmwert nicht auseinanderlaufen; 288 px +// entspricht Tailwind w-72. +const TOOLTIP_WIDTH_PX = 288; +const TOOLTIP_EDGE_PX = 4; + /** * Calendar widget (DASH-05, D-10 read-only), neu gebaut nach dem Vorbild des * alten persoenlichen Dashboards des Anwenders (quick-260916-htc). @@ -30,7 +36,9 @@ import { * * Der Tooltip wird per `createPortal` in `document.body` gerendert, weil die * Karte in widget-wrapper.tsx `overflow-hidden` traegt und ein absolut - * positionierter Tooltip sonst abgeschnitten wuerde. + * positionierter Tooltip sonst abgeschnitten wuerde. Titel im Tooltip + * brechen um (kein truncate); Breite/Klemmung kommen aus + * `TOOLTIP_WIDTH_PX`/`TOOLTIP_EDGE_PX` (quick-260916-j4f). * * Das Ladefenster ist IMMER auf lokale Tagesgrenzen gerundet * (`computeFetchWindow`), damit der Backend-Cache-Schluessel @@ -293,10 +301,14 @@ export function CalendarWidget({ config }: WidgetProps) {
{hoverEvents.slice(0, 5).map((event) => ( @@ -304,7 +316,7 @@ export function CalendarWidget({ config }: WidgetProps) { {event.allDay ? t('calendar.allDay') : formatEventTime(event.start)} - {event.title} + {event.title}
))} {hoverEvents.length > 5 && (