perf(calendar): stop mounting a HoverCard per day cell that can never open

Third instance of the same pattern, and the worst ratio yet. Mantine mounts a HoverCard's
Popover machinery - Popover, PopoverTarget and PopoverDropdown - even when it is disabled.
A month grid is around 42 cells and `disabled` is `isEditMode || eventsForDate.length === 0`,
so on a typical month most days mounted three components for a card that can never open, and
in edit mode every single day did.

Measured on a real board: 42 Popovers, 42 PopoverDropdowns and 42 PopoverTargets - 126 of
this widget's 171 listener-attaching components - in a widget with only 251 DOM nodes. That
is a far worse components-per-node ratio than media-releases, which had 340 across 2,951
nodes.

Returning the day cell directly when disabled is behaviour-identical: a disabled HoverCard
never opens, so nothing observable is lost.

This is now the third place this exact Mantine behaviour has cost real work - after the
shared board context menu and the media-release tooltips. The general rule: Mantine overlay
components mount their full machinery regardless of `disabled`, so `disabled` is a
visual-suppression prop, not a cost-avoidance one. Deciding before rendering is what avoids
the cost.
This commit is contained in:
Thomas Camlong committed 2026-08-11 09:58:13 +02:00
1 parent 7e961d3da4
commit 365b2ed13e
1 file changed
+31 -22
+31 -22
View File
@@ -22,6 +22,36 @@ export const CalendarDay = ({ date, events, disabled, rootHeight, rootWidth }: C
const shouldScaleDown = minAxisSize < 350;
const isSmall = rootHeight < 256;
const cell = (
<Container
h="100%"
w="100%"
p={0}
pt={isSmall ? 0 : 10}
pb={isSmall ? 0 : 10}
m={0}
pos="relative"
style={{
alignContent: "center",
borderRadius: actualItemRadius,
cursor: disabled ? "default" : "pointer",
}}
>
<Text ta={"center"} size={shouldScaleDown ? "xs" : "md"} lh={1}>
{date.getDate()}
</Text>
<NotificationIndicator events={events} isSmall={isSmall} />
</Container>
);
// Mantine mounts a HoverCard's Popover machinery — Popover, PopoverTarget and PopoverDropdown —
// even when it is disabled. A month grid is around 42 cells, and `disabled` is
// `isEditMode || eventsForDate.length === 0`, so on a typical month most days, and in edit mode
// every day, mounted three components for a card that can never open. Measured on a real board:
// 42 Popovers, 42 PopoverDropdowns and 42 PopoverTargets, 126 of this widget's 171
// listener-attaching components, in a widget with only 251 DOM nodes.
if (disabled) return cell;
return (
<HoverCard
position="bottom"
@@ -32,29 +62,8 @@ export const CalendarDay = ({ date, events, disabled, rootHeight, rootWidth }: C
transitionProps={{ transition: "pop" }}
openDelay={350}
closeDelay={400}
disabled={disabled}
>
<HoverCard.Target>
<Container
h="100%"
w="100%"
p={0}
pt={isSmall ? 0 : 10}
pb={isSmall ? 0 : 10}
m={0}
pos="relative"
style={{
alignContent: "center",
borderRadius: actualItemRadius,
cursor: disabled ? "default" : "pointer",
}}
>
<Text ta={"center"} size={shouldScaleDown ? "xs" : "md"} lh={1}>
{date.getDate()}
</Text>
<NotificationIndicator events={events} isSmall={isSmall} />
</Container>
</HoverCard.Target>
<HoverCard.Target>{cell}</HoverCard.Target>
<HoverCard.Dropdown maw="calc(100vw - 24px)" w={512} pe={4} pb={0} style={{ overflow: "hidden" }}>
<CalendarEventList events={events} />
</HoverCard.Dropdown>