diff --git a/docs/docs/options.mdx b/docs/docs/options.mdx index 884f2532..65e163e6 100644 --- a/docs/docs/options.mdx +++ b/docs/docs/options.mdx @@ -73,6 +73,8 @@ import 'react-tooltip/dist/react-tooltip.css' | position | `{ x: number; y: number }` | false | | any `number` value for both `x` and `y` | override the tooltip position on the viewport | | isOpen | boolen | false | handled by internal state | `true` `false` | the tooltip can be controlled or uncontrolled, this attribute can be used to handle show and hide tooltip outside tooltip (can be used **without** `setIsOpen`) | | setIsOpen | function | false | | | the tooltip can be controlled or uncontrolled, this attribute can be used to handle show and hide tooltip outside tooltip | +| afterShow | function | false | | | a function to be called after the tooltip is shown | +| afterHide | function | false | | | a function to be called after the tooltip is hidden | ### Data attributes diff --git a/docs/docs/upgrade-guide/changelog-v4-v5.md b/docs/docs/upgrade-guide/changelog-v4-v5.md index e6ebbb7c..3e7a2fd8 100644 --- a/docs/docs/upgrade-guide/changelog-v4-v5.md +++ b/docs/docs/upgrade-guide/changelog-v4-v5.md @@ -68,8 +68,8 @@ V4 was a great react tooltip component but was built a few years ago, he was bui - [ ] `isCapture` - [ ] `globalEventOff` - [ ] `getContent` - use dynamic `content` -- [ ] `afterShow` - if requested, can be implemented later -- [ ] `afterHide` - if requested, can be implemented later +- [x] `afterShow` +- [x] `afterHide` - [ ] `overridePosition` - use `position` - [ ] `disable` - state can be controlled or uncontrolled - [ ] `scrollHide` - if requested, can be implemented later diff --git a/src/App.tsx b/src/App.tsx index 03bf7b86..3e90a193 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -165,6 +165,43 @@ function App() { /> + +
+ + console.log('After show')} + // eslint-disable-next-line no-console + afterHide={() => console.log('After hide')} + content="Showing tooltip and calling afterShow method" + /> + + + console.log('After show with click')} + // eslint-disable-next-line no-console + afterHide={() => console.log('After hide with click')} + content="Showing tooltip and calling afterShow method" + /> + + + console.log('After show with delay')} + // eslint-disable-next-line no-console + afterHide={() => console.log('After hide with delay')} + content="Showing tooltip and calling afterShow method" + /> +
) } diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index 8b3d9bc9..4a8c0410 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -27,6 +27,8 @@ const Tooltip = ({ clickable = false, style: externalStyles, position, + afterShow, + afterHide, // props handled by controller isHtmlContent = false, content, @@ -39,7 +41,8 @@ const Tooltip = ({ const tooltipHideDelayTimerRef = useRef(null) const [inlineStyles, setInlineStyles] = useState({}) const [inlineArrowStyles, setInlineArrowStyles] = useState({}) - const [show, setShow] = useState(false) + const [show, setShow] = useState(false) + const wasShowing = useRef(false) const [calculatingPosition, setCalculatingPosition] = useState(false) const lastFloatPosition = useRef(null) const { anchorRefs, setActiveAnchor: setProviderActiveAnchor } = useTooltip()(id) @@ -54,6 +57,18 @@ const Tooltip = ({ } } + useEffect(() => { + if (show === wasShowing.current) { + return + } + wasShowing.current = show + if (show) { + afterShow?.() + } else { + afterHide?.() + } + }, [show]) + const handleShowTooltipDelayed = () => { if (tooltipShowDelayTimerRef.current) { clearTimeout(tooltipShowDelayTimerRef.current) @@ -170,7 +185,7 @@ const Tooltip = ({ if (activeAnchor.current?.contains(event.target as HTMLElement)) { return } - setShow(false) + handleShow(false) } // debounce handler to prevent call twice when diff --git a/src/components/Tooltip/TooltipTypes.d.ts b/src/components/Tooltip/TooltipTypes.d.ts index 3f0e7ef7..3e8629e1 100644 --- a/src/components/Tooltip/TooltipTypes.d.ts +++ b/src/components/Tooltip/TooltipTypes.d.ts @@ -54,4 +54,6 @@ export interface ITooltip { position?: IPosition isOpen?: boolean setIsOpen?: (value: boolean) => void + afterShow?: () => void + afterHide?: () => void } diff --git a/src/components/TooltipController/TooltipController.tsx b/src/components/TooltipController/TooltipController.tsx index 2200367b..1425381b 100644 --- a/src/components/TooltipController/TooltipController.tsx +++ b/src/components/TooltipController/TooltipController.tsx @@ -35,6 +35,8 @@ const TooltipController = ({ position, isOpen, setIsOpen, + afterShow, + afterHide, }: ITooltipController) => { const [tooltipContent, setTooltipContent] = useState(content || html) const [tooltipPlace, setTooltipPlace] = useState(place) @@ -190,6 +192,8 @@ const TooltipController = ({ position, isOpen, setIsOpen, + afterShow, + afterHide, } return children ? {children} : diff --git a/src/components/TooltipController/TooltipControllerTypes.d.ts b/src/components/TooltipController/TooltipControllerTypes.d.ts index 0ecff10e..fe977bc9 100644 --- a/src/components/TooltipController/TooltipControllerTypes.d.ts +++ b/src/components/TooltipController/TooltipControllerTypes.d.ts @@ -33,6 +33,8 @@ export interface ITooltipController { position?: IPosition isOpen?: boolean setIsOpen?: (value: boolean) => void + afterShow?: () => void + afterHide?: () => void } declare module 'react' {