Commit 74b63b27 authored by Steven's avatar Steven

perf: disable tooltips in year calendar to fix lag

Fixed issue #5579 where the calendar selection dialog was very laggy.

The root cause was rendering ~365 individual Tooltip components when
opening the year calendar view (one per day with activity). This created
a huge number of DOM nodes and event listeners that caused significant
performance issues.

Changes:
- Added disableTooltips prop to MonthCalendar and CalendarCell components
- Disabled tooltips in YearCalendar's small month views
- Removed unnecessary TooltipProvider wrapper in YearCalendar
- Tooltips remain enabled in the default month calendar view

Performance improvements:
- Eliminates ~365 tooltip instances when dialog opens
- Reduces initial render time significantly
- Makes dialog interactions smooth and responsive

Users can still click on dates to drill down for details if needed.
parent e7605d90
...@@ -11,10 +11,11 @@ export interface CalendarCellProps { ...@@ -11,10 +11,11 @@ export interface CalendarCellProps {
tooltipText: string; tooltipText: string;
onClick?: (date: string) => void; onClick?: (date: string) => void;
size?: CalendarSize; size?: CalendarSize;
disableTooltip?: boolean;
} }
export const CalendarCell = memo((props: CalendarCellProps) => { export const CalendarCell = memo((props: CalendarCellProps) => {
const { day, maxCount, tooltipText, onClick, size = "default" } = props; const { day, maxCount, tooltipText, onClick, size = "default", disableTooltip = false } = props;
const handleClick = () => { const handleClick = () => {
if (day.count > 0 && onClick) { if (day.count > 0 && onClick) {
...@@ -62,7 +63,7 @@ export const CalendarCell = memo((props: CalendarCellProps) => { ...@@ -62,7 +63,7 @@ export const CalendarCell = memo((props: CalendarCellProps) => {
</button> </button>
); );
const shouldShowTooltip = tooltipText && day.count > 0; const shouldShowTooltip = tooltipText && day.count > 0 && !disableTooltip;
if (!shouldShowTooltip) { if (!shouldShowTooltip) {
return button; return button;
......
...@@ -35,7 +35,7 @@ const WeekdayHeader = memo(({ weekDays, size }: WeekdayHeaderProps) => ( ...@@ -35,7 +35,7 @@ const WeekdayHeader = memo(({ weekDays, size }: WeekdayHeaderProps) => (
WeekdayHeader.displayName = "WeekdayHeader"; WeekdayHeader.displayName = "WeekdayHeader";
export const MonthCalendar = memo((props: MonthCalendarProps) => { export const MonthCalendar = memo((props: MonthCalendarProps) => {
const { month, data, maxCount, size = "default", onClick, className } = props; const { month, data, maxCount, size = "default", onClick, className, disableTooltips = false } = props;
const t = useTranslate(); const t = useTranslate();
const { generalSetting } = useInstance(); const { generalSetting } = useInstance();
const today = useTodayDate(); const today = useTodayDate();
...@@ -65,6 +65,7 @@ export const MonthCalendar = memo((props: MonthCalendarProps) => { ...@@ -65,6 +65,7 @@ export const MonthCalendar = memo((props: MonthCalendarProps) => {
tooltipText={getTooltipText(day.count, day.date, t)} tooltipText={getTooltipText(day.count, day.date, t)}
onClick={onClick} onClick={onClick}
size={size} size={size}
disableTooltip={disableTooltips}
/> />
))} ))}
</div> </div>
......
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"; import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
import { memo, useMemo } from "react"; import { memo, useMemo } from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { TooltipProvider } from "@/components/ui/tooltip";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useTranslate } from "@/utils/i18n"; import { useTranslate } from "@/utils/i18n";
import { getMaxYear, MIN_YEAR } from "./constants"; import { getMaxYear, MIN_YEAR } from "./constants";
...@@ -79,7 +78,7 @@ interface MonthCardProps { ...@@ -79,7 +78,7 @@ interface MonthCardProps {
const MonthCard = memo(({ month, data, maxCount, onDateClick }: MonthCardProps) => ( const MonthCard = memo(({ month, data, maxCount, onDateClick }: MonthCardProps) => (
<article className="flex flex-col gap-2 rounded-xl border border-border/20 bg-muted/5 p-3 transition-colors hover:bg-muted/10"> <article className="flex flex-col gap-2 rounded-xl border border-border/20 bg-muted/5 p-3 transition-colors hover:bg-muted/10">
<header className="text-[10px] font-medium text-muted-foreground/80 uppercase tracking-widest">{getMonthLabel(month)}</header> <header className="text-[10px] font-medium text-muted-foreground/80 uppercase tracking-widest">{getMonthLabel(month)}</header>
<MonthCalendar month={month} data={data} maxCount={maxCount} size="small" onClick={onDateClick} /> <MonthCalendar month={month} data={data} maxCount={maxCount} size="small" onClick={onDateClick} disableTooltips />
</article> </article>
)); ));
MonthCard.displayName = "MonthCard"; MonthCard.displayName = "MonthCard";
...@@ -105,13 +104,11 @@ export const YearCalendar = memo(({ selectedYear, data, onYearChange, onDateClic ...@@ -105,13 +104,11 @@ export const YearCalendar = memo(({ selectedYear, data, onYearChange, onDateClic
canGoNext={canGoNext} canGoNext={canGoNext}
/> />
<TooltipProvider>
<div className="grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 animate-fade-in"> <div className="grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 animate-fade-in">
{months.map((month) => ( {months.map((month) => (
<MonthCard key={month} month={month} data={yearData} maxCount={yearMaxCount} onDateClick={onDateClick} /> <MonthCard key={month} month={month} data={yearData} maxCount={yearMaxCount} onDateClick={onDateClick} />
))} ))}
</div> </div>
</TooltipProvider>
</section> </section>
); );
}); });
......
...@@ -27,6 +27,7 @@ export interface MonthCalendarProps { ...@@ -27,6 +27,7 @@ export interface MonthCalendarProps {
size?: CalendarSize; size?: CalendarSize;
onClick?: (date: string) => void; onClick?: (date: string) => void;
className?: string; className?: string;
disableTooltips?: boolean;
} }
export interface YearCalendarProps { export interface YearCalendarProps {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment