Skip to content

Commit f10cc04

Browse files
micahgodboltkhmakotolayershifter
authored
Tooltip - support custom mountNode (#22134)
* Add mountNode prop to tooltip * update rooltip api * change file * fix test in story * update example to use setRef * remove default value of mountNode * Update packages/react-tooltip/src/stories/TooltipCustomMount.stories.tsx Co-authored-by: Makoto Morimoto <[email protected]> * Update change/@fluentui-react-tooltip-79df9179-1dd1-4817-9d7b-623d2a2fe436.json Co-authored-by: Oleksandr Fediashov <[email protected]> * Update packages/react-tooltip/src/stories/TooltipCustomMount.stories.tsx Co-authored-by: Oleksandr Fediashov <[email protected]> Co-authored-by: Makoto Morimoto <[email protected]> Co-authored-by: Oleksandr Fediashov <[email protected]>
1 parent dc052f7 commit f10cc04

File tree

7 files changed

+41
-4
lines changed

7 files changed

+41
-4
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Add mountNode prop",
4+
"packageName": "@fluentui/react-tooltip",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/react-tooltip/etc/react-tooltip.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import type { ComponentProps } from '@fluentui/react-utilities';
88
import type { ComponentState } from '@fluentui/react-utilities';
99
import type { FluentTriggerComponent } from '@fluentui/react-utilities';
10+
import type { PortalProps } from '@fluentui/react-portal';
1011
import type { PositioningShorthand } from '@fluentui/react-positioning';
1112
import * as React_2 from 'react';
1213
import type { Slot } from '@fluentui/react-utilities';

packages/react-tooltip/src/components/Tooltip/Tooltip.types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as React from 'react';
22
import type { PositioningShorthand } from '@fluentui/react-positioning';
33
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';
4+
import type { PortalProps } from '@fluentui/react-portal';
45

56
/**
67
* Slot properties for Tooltip
@@ -15,7 +16,7 @@ export type TooltipSlots = {
1516
/**
1617
* Properties and state for Tooltip
1718
*/
18-
type TooltipCommons = {
19+
type TooltipCommons = Pick<PortalProps, 'mountNode'> & {
1920
/**
2021
* (Required) Specifies whether this tooltip is acting as the description or label of its trigger element.
2122
*

packages/react-tooltip/src/components/Tooltip/renderTooltip.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const renderTooltip_unstable = (state: TooltipState) => {
1313
<>
1414
{state.children}
1515
{state.shouldRenderTooltip && (
16-
<Portal>
16+
<Portal mountNode={state.mountNode}>
1717
<slots.content {...slotProps.content}>
1818
{state.withArrow && <div ref={state.arrowRef} className={state.arrowClassName} />}
1919
{state.content.children}

packages/react-tooltip/src/components/Tooltip/useTooltip.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const useTooltip_unstable = (props: TooltipProps): TooltipState => {
4040
relationship,
4141
showDelay = 250,
4242
hideDelay = 250,
43+
mountNode,
4344
} = props;
4445

4546
const [visible, setVisibleInternal] = useControllableState({ state: props.visible, initialState: false });
@@ -65,7 +66,7 @@ export const useTooltip_unstable = (props: TooltipProps): TooltipState => {
6566
visible,
6667
shouldRenderTooltip: visible,
6768
appearance,
68-
69+
mountNode,
6970
// Slots
7071
components: {
7172
content: 'div',

packages/react-tooltip/src/stories/Tooltip.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export { RelationshipDescription } from './TooltipRelationshipDescription.storie
88
export { Inverted } from './TooltipInverted.stories';
99
export { WithArrow } from './TooltipWithArrow.stories';
1010
export { Styled } from './TooltipStyled.stories';
11-
11+
export { CustomMount } from './TooltipCustomMount.stories';
1212
export { Controlled } from './TooltipControlled.stories';
1313
export { Positioning } from './TooltipPositioning.stories';
1414
export { Target } from './TooltipTarget.stories';
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import * as React from 'react';
2+
3+
import { Tooltip, TooltipProps } from '../Tooltip';
4+
import { Button } from '@fluentui/react-button';
5+
import { SlideTextRegular } from '@fluentui/react-icons';
6+
7+
export const CustomMount = (props: Partial<TooltipProps>) => {
8+
const [ref, setRef] = React.useState<HTMLElement | null>();
9+
10+
return (
11+
<>
12+
<Tooltip mountNode={ref} content="Example tooltip" relationship="label" {...props}>
13+
<Button icon={<SlideTextRegular />} size="large" />
14+
</Tooltip>
15+
<div ref={setRef} />
16+
</>
17+
);
18+
};
19+
20+
CustomMount.parameters = {
21+
docs: {
22+
description: {
23+
story: `Tooltips are rendered in a React Portal. By default that Portal is the outermost div.
24+
A custom \`mountNode\` can be provided in the case that the tooltip needs to be rendered elsewhere.`,
25+
},
26+
},
27+
};

0 commit comments

Comments
 (0)