Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/docs/options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/upgrade-guide/changelog-v4-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 37 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,43 @@ function App() {
/>
</div>
</div>

<div style={{ marginTop: '1rem' }}>
<button id="buttonCallbacks">Check the dev console</button>
<Tooltip
place="bottom"
anchorId="buttonCallbacks"
// eslint-disable-next-line no-console
afterShow={() => console.log('After show')}
// eslint-disable-next-line no-console
afterHide={() => console.log('After hide')}
content="Showing tooltip and calling afterShow method"
/>

<button id="buttonCallbacksClick">With click event</button>
<Tooltip
events={['click']}
place="bottom"
anchorId="buttonCallbacksClick"
// eslint-disable-next-line no-console
afterShow={() => 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"
/>

<button id="buttonCallbacksDelay">With delay</button>
<Tooltip
delayShow={1000}
place="bottom"
anchorId="buttonCallbacksDelay"
// eslint-disable-next-line no-console
afterShow={() => 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"
/>
</div>
</main>
)
}
Expand Down
19 changes: 17 additions & 2 deletions src/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const Tooltip = ({
clickable = false,
style: externalStyles,
position,
afterShow,
afterHide,
// props handled by controller
isHtmlContent = false,
content,
Expand All @@ -39,7 +41,8 @@ const Tooltip = ({
const tooltipHideDelayTimerRef = useRef<NodeJS.Timeout | null>(null)
const [inlineStyles, setInlineStyles] = useState({})
const [inlineArrowStyles, setInlineArrowStyles] = useState({})
const [show, setShow] = useState<boolean>(false)
const [show, setShow] = useState(false)
const wasShowing = useRef(false)
const [calculatingPosition, setCalculatingPosition] = useState(false)
const lastFloatPosition = useRef<IPosition | null>(null)
const { anchorRefs, setActiveAnchor: setProviderActiveAnchor } = useTooltip()(id)
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/components/Tooltip/TooltipTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,6 @@ export interface ITooltip {
position?: IPosition
isOpen?: boolean
setIsOpen?: (value: boolean) => void
afterShow?: () => void
afterHide?: () => void
}
4 changes: 4 additions & 0 deletions src/components/TooltipController/TooltipController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const TooltipController = ({
position,
isOpen,
setIsOpen,
afterShow,
afterHide,
}: ITooltipController) => {
const [tooltipContent, setTooltipContent] = useState(content || html)
const [tooltipPlace, setTooltipPlace] = useState(place)
Expand Down Expand Up @@ -190,6 +192,8 @@ const TooltipController = ({
position,
isOpen,
setIsOpen,
afterShow,
afterHide,
}

return children ? <Tooltip {...props}>{children}</Tooltip> : <Tooltip {...props} />
Expand Down
2 changes: 2 additions & 0 deletions src/components/TooltipController/TooltipControllerTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export interface ITooltipController {
position?: IPosition
isOpen?: boolean
setIsOpen?: (value: boolean) => void
afterShow?: () => void
afterHide?: () => void
}

declare module 'react' {
Expand Down