diff --git a/client/src/components/Planner/DayPlanSidebar.tsx b/client/src/components/Planner/DayPlanSidebar.tsx index a52d3afbb..3566e83c5 100644 --- a/client/src/components/Planner/DayPlanSidebar.tsx +++ b/client/src/components/Planner/DayPlanSidebar.tsx @@ -195,7 +195,6 @@ function useDayPlanSidebar(props: DayPlanSidebarProps) { const [lockedIds, setLockedIds] = useState(new Set()) const [lockHoverId, setLockHoverId] = useState(null) const [undoHover, setUndoHover] = useState(false) - const [pdfHover, setPdfHover] = useState(false) const [icsHover, setIcsHover] = useState(false) const [hoveredAssignmentId, setHoveredAssignmentId] = useState(null) // Transit rows fold their itinerary out inline (#1065). @@ -984,8 +983,6 @@ function useDayPlanSidebar(props: DayPlanSidebarProps) { setLockHoverId, undoHover, setUndoHover, - pdfHover, - setPdfHover, icsHover, setIcsHover, hoveredAssignmentId, @@ -1155,8 +1152,6 @@ const DayPlanSidebar = React.memo(function DayPlanSidebar(props: DayPlanSidebarP setLockHoverId, undoHover, setUndoHover, - pdfHover, - setPdfHover, icsHover, setIcsHover, hoveredAssignmentId, @@ -1267,8 +1262,6 @@ const DayPlanSidebar = React.memo(function DayPlanSidebar(props: DayPlanSidebarP t={t} locale={locale} toast={toast} - pdfHover={pdfHover} - setPdfHover={setPdfHover} icsHover={icsHover} setIcsHover={setIcsHover} expandedDays={expandedDays} diff --git a/client/src/components/Planner/DayPlanSidebarToolbar.test.tsx b/client/src/components/Planner/DayPlanSidebarToolbar.test.tsx index b0a3ec181..a354acb3e 100644 --- a/client/src/components/Planner/DayPlanSidebarToolbar.test.tsx +++ b/client/src/components/Planner/DayPlanSidebarToolbar.test.tsx @@ -46,8 +46,6 @@ function makeProps(overrides: Partial {}), icsHover: false, setIcsHover: vi.fn((_v: boolean) => {}), expandedDays: new Set(), @@ -97,21 +95,29 @@ describe('DayPlanSidebarToolbar', () => { await waitFor(() => expect(toast.error).toHaveBeenCalledWith('dayplan.pdfError: font missing')) }) - it('FE-PLANNER-DPTOOLBAR-003: hovering the PDF button reports the hover state upward', async () => { + it('FE-PLANNER-DPTOOLBAR-003: hovering the PDF button shows the export tooltip', async () => { const user = userEvent.setup() - const setPdfHover = vi.fn((_v: boolean) => {}) - render() + render() + expect(screen.queryByText('dayplan.pdfTooltip')).not.toBeInTheDocument() await user.hover(screen.getByText('dayplan.pdf')) - expect(setPdfHover).toHaveBeenCalledWith(true) + await waitFor(() => expect(screen.getByText('dayplan.pdfTooltip')).toBeInTheDocument()) await user.unhover(screen.getByText('dayplan.pdf')) - expect(setPdfHover).toHaveBeenCalledWith(false) + await waitFor(() => expect(screen.queryByText('dayplan.pdfTooltip')).not.toBeInTheDocument()) }) - it('FE-PLANNER-DPTOOLBAR-004: pdfHover renders the export tooltip', () => { - const { rerender } = render() - expect(screen.queryByText('dayplan.pdfTooltip')).not.toBeInTheDocument() - rerender() - expect(screen.getByText('dayplan.pdfTooltip')).toBeInTheDocument() + // The button sits at the right edge of the leftmost pane. Its own tooltip was + // anchored with `right: 0` and never wrapped, so a long label ran off the left + // of the window. The shared tooltip is portalled and clamped to the viewport. + it('FE-PLANNER-DPTOOLBAR-004: the export tooltip stays inside the window', async () => { + const user = userEvent.setup() + render() + await user.hover(screen.getByText('dayplan.pdf')) + const tip = await screen.findByText('dayplan.pdfTooltip') + expect(tip.closest('[role="tooltip"]')).not.toBeNull() + expect(tip.parentElement).toBe(document.body) + expect(tip.style.position).toBe('fixed') + // Placed once measured, and never to the left of the window edge. + await waitFor(() => expect(parseFloat(tip.style.left)).toBeGreaterThanOrEqual(0)) }) // ── ICS menu ────────────────────────────────────────────────────────────── diff --git a/client/src/components/Planner/DayPlanSidebarToolbar.tsx b/client/src/components/Planner/DayPlanSidebarToolbar.tsx index e52ea50c8..eb1925583 100644 --- a/client/src/components/Planner/DayPlanSidebarToolbar.tsx +++ b/client/src/components/Planner/DayPlanSidebarToolbar.tsx @@ -22,8 +22,6 @@ interface DayPlanSidebarToolbarProps { t: (key: string, params?: Record) => string locale: string toast: ReturnType - pdfHover: boolean - setPdfHover: (v: boolean) => void icsHover: boolean setIcsHover: (v: boolean) => void expandedDays: Set @@ -41,7 +39,7 @@ interface DayPlanSidebarToolbarProps { export function DayPlanSidebarToolbar({ tripId, trip, days, places, categories, assignments, reservations, dayNotes, allConnectionsShown = false, onToggleAllConnections, - t, locale, toast, pdfHover, setPdfHover, setIcsHover, + t, locale, toast, setIcsHover, expandedDays, setExpandedDays, onUndo, canUndo, undoHover, setUndoHover, lastActionLabel, canEditDays, onReorderDays, onAddDay, }: DayPlanSidebarToolbarProps) { @@ -74,6 +72,7 @@ export function DayPlanSidebarToolbar({
+ - {pdfHover && ( -
- {t('dayplan.pdfTooltip')} -
- )} +