diff --git a/docs/pages/base-ui/api/use-tooltip.json b/docs/pages/base-ui/api/use-tooltip.json index 9a7c1df1df..2f55635a60 100644 --- a/docs/pages/base-ui/api/use-tooltip.json +++ b/docs/pages/base-ui/api/use-tooltip.json @@ -90,6 +90,7 @@ }, "required": true }, + "instantOpen": { "type": { "name": "boolean", "description": "boolean" }, "required": true }, "mounted": { "type": { "name": "boolean", "description": "boolean" }, "required": true }, "setAnchorEl": { "type": { diff --git a/docs/pages/experiments/tooltip.tsx b/docs/pages/experiments/tooltip.tsx index 67fb09588e..a2b59a3aec 100644 --- a/docs/pages/experiments/tooltip.tsx +++ b/docs/pages/experiments/tooltip.tsx @@ -35,13 +35,21 @@ export const TooltipContent = styled(Tooltip.Content)` &[data-transition] { transition-property: opacity, transform; - transition-duration: 0.15s; + transition-duration: 0.2s; opacity: 0; transform: scale(0.9); &[data-status='opening'] { opacity: 1; transform: scale(1); + + &[data-instant-open] { + transition-duration: 0s; + } + } + + &[data-status='closing'][data-instant-open] { + transition-duration: 0s; } } @@ -84,26 +92,36 @@ export default function TooltipTransitionExperiment() { fontFamily: '"IBM Plex Sans", sans-serif', }} > -

Transition

- - - - Anchor - - - Tooltip - - -

Animation

- - - Anchor - - - Tooltip - - -
+

Transition With Group

+
+ + + + Anchor + + + Tooltip + + + + + Anchor + + + Tooltip + + + +
+

Animation

+ + + Anchor + + + Tooltip + + ); } diff --git a/docs/translations/api-docs/use-tooltip/use-tooltip.json b/docs/translations/api-docs/use-tooltip/use-tooltip.json index 2b9cd6f1b9..1e0a777579 100644 --- a/docs/translations/api-docs/use-tooltip/use-tooltip.json +++ b/docs/translations/api-docs/use-tooltip/use-tooltip.json @@ -50,6 +50,9 @@ "floatingContext": { "description": "The Floating UI context of the tooltip element." }, "getAnchorProps": { "description": "Props to spread on the anchor element." }, "getContentProps": { "description": "Props to spread on the tooltip element." }, + "instantOpen": { + "description": "If true, the tooltip is in a phase where it should be instantly open while in a group." + }, "mounted": { "description": "Whether the tooltip is mounted, including CSS transitions or animations." }, diff --git a/packages/mui-base/src/Tooltip/TooltipContent.tsx b/packages/mui-base/src/Tooltip/TooltipContent.tsx index fc76028fe9..1879ba339c 100644 --- a/packages/mui-base/src/Tooltip/TooltipContent.tsx +++ b/packages/mui-base/src/Tooltip/TooltipContent.tsx @@ -117,6 +117,7 @@ const TooltipContent = React.forwardRef(function TooltipContent( ['data-side' as string]: tooltip.side, ['data-alignment' as string]: tooltip.alignment, ['data-status' as string]: tooltip.status, + ['data-instant-open' as string]: tooltip.instantOpen || undefined, ...otherProps, }; diff --git a/packages/mui-base/src/useTooltip/useTooltip.ts b/packages/mui-base/src/useTooltip/useTooltip.ts index 7de7ba3800..2550292089 100644 --- a/packages/mui-base/src/useTooltip/useTooltip.ts +++ b/packages/mui-base/src/useTooltip/useTooltip.ts @@ -184,11 +184,20 @@ export function useTooltip(params: UseTooltipParameters): UseTooltipReturnValue return undefined; }, [keepMounted, mounted, elements, update]); + const { delay: groupDelay, isInstantPhase, currentId } = useDelayGroup(context); + const renderedSide = getSide(renderedPlacement); const renderedAlignment = getAlignment(renderedPlacement) || 'center'; const isHidden = hideWhenDetached && middlewareData.hide?.referenceHidden; - const { delay: groupDelay } = useDelayGroup(context); + let isInstantOpen = isInstantPhase; + if (isInstantPhase) { + if (open) { + isInstantOpen = true; + } else if (currentId === context.floatingId) { + isInstantOpen = false; + } + } const hover = useHover(context, { delay: @@ -232,6 +241,7 @@ export function useTooltip(params: UseTooltipParameters): UseTooltipReturnValue ['data-side' as string]: renderedSide, ['data-alignment' as string]: renderedAlignment, ['data-status' as string]: status, + ['data-instant-open' as string]: isInstantOpen || undefined, style: { ...floatingStyles, maxWidth: 'var(--available-width)', @@ -255,6 +265,7 @@ export function useTooltip(params: UseTooltipParameters): UseTooltipReturnValue status, setMounted, refs, + isInstantOpen, ], ); @@ -270,6 +281,7 @@ export function useTooltip(params: UseTooltipParameters): UseTooltipReturnValue floatingContext: context, side: renderedSide, alignment: renderedAlignment, + instantOpen: isInstantOpen, }), [ status, @@ -281,6 +293,7 @@ export function useTooltip(params: UseTooltipParameters): UseTooltipReturnValue context, renderedSide, renderedAlignment, + isInstantOpen, ], ); } diff --git a/packages/mui-base/src/useTooltip/useTooltip.types.ts b/packages/mui-base/src/useTooltip/useTooltip.types.ts index 041c6ec2b4..cf80635e02 100644 --- a/packages/mui-base/src/useTooltip/useTooltip.types.ts +++ b/packages/mui-base/src/useTooltip/useTooltip.types.ts @@ -154,6 +154,10 @@ export interface UseTooltipReturnValue { * The status of the tooltip element when considering CSS transitions or animations. */ status: Status; + /** + * If `true`, the tooltip is in a phase where it should be instantly open while in a group. + */ + instantOpen: boolean; } export interface UseTooltipOpenStateReturnValue {