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 && (