From 4b7ea0c98fb2fe583bdd0330aac3f6b4308dff8d Mon Sep 17 00:00:00 2001 From: Eunjae Lee Date: Mon, 2 Feb 2026 15:40:20 +0100 Subject: [PATCH] feat: update current time indicator on page refocus (#27503) Add updateCurrentTimeOnFocus prop to Calendar component that enables the current time indicator to update when the page is refocused. This helps users see the accurate current time after switching tabs. Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Peer Richelsen --- .../components/BookingCalendarView.tsx | 7 ++-- .../weeklyview/components/Calendar.tsx | 20 +++++++--- .../components/currentTime/index.tsx | 37 +++++++++++++------ .../calendars/weeklyview/types/state.ts | 6 ++- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/apps/web/modules/bookings/components/BookingCalendarView.tsx b/apps/web/modules/bookings/components/BookingCalendarView.tsx index b733bfebb6..ae539e4e23 100644 --- a/apps/web/modules/bookings/components/BookingCalendarView.tsx +++ b/apps/web/modules/bookings/components/BookingCalendarView.tsx @@ -1,14 +1,12 @@ "use client"; -import { useMemo, useEffect } from "react"; - import dayjs from "@calcom/dayjs"; import { useTimePreferences } from "@calcom/features/bookings/lib"; -import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar"; import type { CalendarEvent } from "@calcom/features/calendars/weeklyview/types/events"; import { useGetTheme } from "@calcom/lib/hooks/useTheme"; +import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar"; import { useBanners } from "@calcom/web/modules/shell/banners/useBanners"; - +import { useEffect, useMemo } from "react"; import { useBookingDetailsSheetStore } from "../store/bookingDetailsSheetStore"; import type { BookingOutput } from "../types"; @@ -101,6 +99,7 @@ export function BookingCalendarView({ }} showTimezone hideHeader + updateCurrentTimeOnFocus /> diff --git a/apps/web/modules/calendars/weeklyview/components/Calendar.tsx b/apps/web/modules/calendars/weeklyview/components/Calendar.tsx index 8133909b18..9e12df836a 100644 --- a/apps/web/modules/calendars/weeklyview/components/Calendar.tsx +++ b/apps/web/modules/calendars/weeklyview/components/Calendar.tsx @@ -1,13 +1,16 @@ -import React, { useEffect, useMemo, useRef } from "react"; - +import { + CalendarStoreContext, + createCalendarStore, + useCalendarStore, +} from "@calcom/features/calendars/weeklyview/state/store"; import classNames from "@calcom/ui/classNames"; - -import { CalendarStoreContext, createCalendarStore, useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store"; +import type React from "react"; +import { useEffect, useMemo, useRef } from "react"; import "@calcom/features/calendars/weeklyview/styles/styles.css"; import type { CalendarComponentProps } from "@calcom/features/calendars/weeklyview/types/state"; import { getDaysBetweenDates, getHoursToDisplay } from "@calcom/features/calendars/weeklyview/utils"; -import { DateValues } from "./DateValues"; import { CurrentTime } from "./currentTime"; +import { DateValues } from "./DateValues"; import { AvailableCellsForDay, EmptyCell } from "./event/Empty"; import { EventList } from "./event/EventList"; import { SchedulerColumns } from "./grid"; @@ -35,6 +38,7 @@ function CalendarInner(props: CalendarComponentProps) { const showBorder = useCalendarStore((state) => state.showBorder ?? true); const borderColor = useCalendarStore((state) => state.borderColor ?? "default"); const scrollToCurrentTime = useCalendarStore((state) => state.scrollToCurrentTime ?? true); + const updateCurrentTimeOnFocus = useCalendarStore((state) => state.updateCurrentTimeOnFocus ?? false); const days = useMemo(() => getDaysBetweenDates(startDate, endDate), [startDate, endDate]); @@ -75,7 +79,11 @@ function CalendarInner(props: CalendarComponentProps) { borderColor={borderColor} />
- +
(null); @@ -27,29 +27,44 @@ export function CurrentTime({ endHour: state.endHour || 23, })); - useEffect(() => { - // Set the container scroll position based on the current time. - - const currentDateTime = dayjs().tz(timezone); // Get current date and time in the specified timezone - + const updateCurrentTimePosition = useCallback(() => { + const currentDateTime = dayjs().tz(timezone); const currentHour = currentDateTime.hour(); const currentMinute = currentDateTime.minute(); if (currentHour > endHour || currentHour < startHour) { setCurrentTimePos(null); + return; } const minutesFromStart = calculateMinutesFromStart(startHour, currentHour, currentMinute); setCurrentTimePos(minutesFromStart); + }, [timezone, startHour, endHour]); + + useEffect(() => { + updateCurrentTimePosition(); if (!scrollToCurrentTime || !currentTimeRef.current || scrolledIntoView) return; - // Within a small timeout so element has time to render. setTimeout(() => { - // Doesn't seem to cause any issue. Put it under condition if needed currentTimeRef?.current?.scrollIntoView({ block: "center" }); setScrolledIntoView(true); }, 100); - }, [startHour, endHour, scrolledIntoView, timezone, scrollToCurrentTime]); + }, [updateCurrentTimePosition, scrolledIntoView, scrollToCurrentTime]); + + useEffect(() => { + if (!updateOnFocus) return; + + const handleVisibilityChange = () => { + if (document.visibilityState === "visible") { + updateCurrentTimePosition(); + } + }; + + document.addEventListener("visibilitychange", handleVisibilityChange); + return () => { + document.removeEventListener("visibilitychange", handleVisibilityChange); + }; + }, [updateOnFocus, updateCurrentTimePosition]); return (