Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add popover anchor tooltip #30150

Merged
merged 9 commits into from
Oct 23, 2023
2 changes: 1 addition & 1 deletion src/components/AvatarWithImagePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize';
import variables from '../styles/variables';
import CONST from '../CONST';
import SpinningIndicatorAnimation from '../styles/animation/SpinningIndicatorAnimation';
import Tooltip from './Tooltip';
import Tooltip from './Tooltip/PopoverAnchorTooltip';
import stylePropTypes from '../styles/stylePropTypes';
import * as FileUtils from '../libs/fileDownload/FileUtils';
import getImageResolution from '../libs/fileDownload/getImageResolution';
Expand Down
2 changes: 1 addition & 1 deletion src/components/BaseMiniContextMenuItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import styles from '../styles/styles';
import * as StyleUtils from '../styles/StyleUtils';
import getButtonState from '../libs/getButtonState';
import variables from '../styles/variables';
import Tooltip from './Tooltip';
import Tooltip from './Tooltip/PopoverAnchorTooltip';
import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback';
import ReportActionComposeFocusManager from '../libs/ReportActionComposeFocusManager';
import DomUtils from '../libs/DomUtils';
Expand Down
2 changes: 1 addition & 1 deletion src/components/EmojiPicker/EmojiPickerButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styles from '../../styles/styles';
import * as StyleUtils from '../../styles/StyleUtils';
import getButtonState from '../../libs/getButtonState';
import * as Expensicons from '../Icon/Expensicons';
import Tooltip from '../Tooltip';
import Tooltip from '../Tooltip/PopoverAnchorTooltip';
import Icon from '../Icon';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import * as EmojiPickerAction from '../../libs/actions/EmojiPickerAction';
Expand Down
2 changes: 1 addition & 1 deletion src/components/FloatingActionButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as Expensicons from './Icon/Expensicons';
import styles from '../styles/styles';
import * as StyleUtils from '../styles/StyleUtils';
import themeColors from '../styles/themes/default';
import Tooltip from './Tooltip';
import Tooltip from './Tooltip/PopoverAnchorTooltip';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import PressableWithFeedback from './Pressable/PressableWithFeedback';
import variables from '../styles/variables';
Expand Down
2 changes: 1 addition & 1 deletion src/components/Reactions/AddReactionBubble.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {useRef, useEffect} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import Tooltip from '../Tooltip';
import Tooltip from '../Tooltip/PopoverAnchorTooltip';
import styles from '../../styles/styles';
import * as StyleUtils from '../../styles/StyleUtils';
import Icon from '../Icon';
Expand Down
2 changes: 1 addition & 1 deletion src/components/ThreeDotsMenu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Icon from '../Icon';
import PopoverMenu from '../PopoverMenu';
import styles from '../../styles/styles';
import useLocalize from '../../hooks/useLocalize';
import Tooltip from '../Tooltip';
import Tooltip from '../Tooltip/PopoverAnchorTooltip';
import * as Expensicons from '../Icon/Expensicons';
import ThreeDotsMenuItemPropTypes from './ThreeDotsMenuItemPropTypes';
import CONST from '../../CONST';
Expand Down
3 changes: 2 additions & 1 deletion src/components/Tooltip/BaseTooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function chooseBoundingBox(target, clientX, clientY) {
return target.getBoundingClientRect();
}

function Tooltip({children, numberOfLines, maxWidth, text, renderTooltipContent, renderTooltipContentKey, shouldHandleScroll, shiftHorizontal, shiftVertical}) {
function Tooltip({children, numberOfLines, maxWidth, text, renderTooltipContent, renderTooltipContentKey, shouldHandleScroll, shiftHorizontal, shiftVertical, tooltipRef}) {
const {preferredLocale} = useLocalize();
const {windowWidth} = useWindowDimensions();

Expand Down Expand Up @@ -197,6 +197,7 @@ function Tooltip({children, numberOfLines, maxWidth, text, renderTooltipContent,
<BoundsObserver
enabled={isVisible}
onBoundsChange={updateBounds}
ref={tooltipRef}
>
<Hoverable
onMouseEnter={updateTargetAndMousePosition}
Expand Down
53 changes: 53 additions & 0 deletions src/components/Tooltip/PopoverAnchorTooltip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, {useContext, useRef, useMemo} from 'react';
import PropTypes from 'prop-types';
import {propTypes as tooltipPropTypes, defaultProps as tooltipDefaultProps} from './tooltipPropTypes';
import BaseTooltip from './BaseTooltip';
import {PopoverContext} from '../PopoverProvider';

const propTypes = {
...tooltipPropTypes,

/** Whether the actual Tooltip should be rendered. If false, it's just going to return the children */
shouldRender: PropTypes.bool,
};

const defaultProps = {
...tooltipDefaultProps,
shouldRender: true,
};

function PopoverAnchorTooltip({shouldRender, children, ...props}) {
const {isOpen, popover} = useContext(PopoverContext);

luacmartins marked this conversation as resolved.
Show resolved Hide resolved
const tooltipRef = useRef(null);

const isPopoverRelatedToTooltipOpen = useMemo(() => {
// eslint-disable-next-line
const tooltipNode = tooltipRef.current ? tooltipRef.current._childNode : null;
if (isOpen && popover && popover.anchorRef.current && tooltipNode && (tooltipNode.contains(popover.anchorRef.current) || tooltipNode === popover.anchorRef.current)) {
luacmartins marked this conversation as resolved.
Show resolved Hide resolved
return true;
}

return false;
}, [isOpen, popover]);

if (!shouldRender || isPopoverRelatedToTooltipOpen) {
return children;
}
Comment on lines +40 to +42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This conditional render caused regression.
More details: #31155 (comment)


return (
<BaseTooltip
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
tooltipRef={tooltipRef}
>
{children}
</BaseTooltip>
);
}

PopoverAnchorTooltip.displayName = 'PopoverAnchorTooltip';
PopoverAnchorTooltip.propTypes = propTypes;
PopoverAnchorTooltip.defaultProps = defaultProps;

export default PopoverAnchorTooltip;
5 changes: 5 additions & 0 deletions src/components/Tooltip/tooltipPropTypes.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
import refPropType from '../refPropTypes';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import refPropType from '../refPropTypes';
import refPropTypes from '../refPropTypes';

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handled

import variables from '../../styles/variables';
import CONST from '../../CONST';

Expand Down Expand Up @@ -31,6 +32,9 @@ const propTypes = {

/** passes this down to Hoverable component to decide whether to handle the scroll behaviour to show hover once the scroll ends */
shouldHandleScroll: PropTypes.bool,

/** Reference to the tooltip container */
tooltipRef: refPropType,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
tooltipRef: refPropType,
tooltipRef: refPropTypes,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handled

};

const defaultProps = {
Expand All @@ -42,6 +46,7 @@ const defaultProps = {
renderTooltipContent: undefined,
renderTooltipContentKey: [],
shouldHandleScroll: false,
tooltipRef: () => {},
};

export {propTypes, defaultProps};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import themeColors from '../../styles/themes/default';
import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import compose from '../../libs/compose';
import Tooltip from '../Tooltip';
import Tooltip from '../Tooltip/PopoverAnchorTooltip';
import {propTypes as videoChatButtonAndMenuPropTypes, defaultProps} from './videoChatButtonAndMenuPropTypes';
import * as Session from '../../libs/actions/Session';
import PressableWithoutFeedback from '../Pressable/PressableWithoutFeedback';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import AttachmentPicker from '../../../../components/AttachmentPicker';
import * as Report from '../../../../libs/actions/Report';
import PopoverMenu from '../../../../components/PopoverMenu';
import CONST from '../../../../CONST';
import Tooltip from '../../../../components/Tooltip';
import Tooltip from '../../../../components/Tooltip/PopoverAnchorTooltip';
import * as Browser from '../../../../libs/Browser';
import PressableWithFeedback from '../../../../components/Pressable/PressableWithFeedback';
import useLocalize from '../../../../hooks/useLocalize';
Expand Down
Loading