Reputation: 765
I want to render my TooltipComponent
on a button only when the user click on this button and specific condition holds.
I'm familiar with the react-tooltip
library, but I don't want to use it, my opinion is not positive about this lib. In this library there is a ReactTooltop.show
function.
I want to be able to do something like (again, without using this lib:
const onBtnClick = () => {
if(...condition...){
MyTooltip.show(btnRef, ...); // maybe pass some arguments like tooltip text...
}
}
Any idea how can i implement this?
Thanks!
Upvotes: 0
Views: 1846
Reputation: 4987
What you need is a popover
, here is an example. You can find some on the internet but it's also easy to recreate :
.ts:
import React, { Component } from "react";
import { render } from "react-dom";
import "./style.css";
const App = () => {
const [isPopoverVisible, setPopoverVisibility] = React.useState(false);
const togglePopover = () => {
if (!isPopoverVisible) {
setPopoverVisibility(!isPopoverVisible);
} else {
setTimeout(() => setPopoverVisibility(!isPopoverVisible), 20000);
}
};
return (
<>
<div>
Content Content Content Content Content Content Content Content Content
Content Content Content Content Content Content Content Content Content
Content Content Content Content Content Content Content Content Content
Content Content Content Content Content Content Content Content Content
Content Content Content Content
</div>
<span>Some content</span>
<Popover
isVisible={isPopoverVisible}
resetVisibility={togglePopover}
>
<button onClick={() => togglePopover()}>coucou</button>
</Popover>
<div>other content</div>
</>
);
};
const Popover = ({ children, isVisible, resetVisibility, position }) => {
const [classes, setClasses] = React.useState("popover");
const [style, setStyle] = React.useState({});
const childrenRef = React.createRef();
const popoverMessageRef = React.createRef();
React.useEffect(() => {
const messagePos = popoverMessageRef.current.getBoundingClientRect();
const childrenPos = childrenRef.current.getBoundingClientRect();
// x and y from getBoundingClientRect() dos not take into account the padding, we need to add it to our calculs
const messagePaddingFull = window
.getComputedStyle(popoverMessageRef.current)
.getPropertyValue("padding");
const messagePadding =
messagePaddingFull.substring(0, messagePaddingFull.length - 2);
if(position){
if (position.toLowerCase() === "top") {
setStyle({
top: `${childrenPos.y - messagePos.height - 10}px`,
left: `${(childrenPos.x - messagePadding) - childrenPos.width / 2}px`
});
} else if(position.toLowerCase() === "left"){
setStyle({
top: `${(+childrenPos.y + +messagePadding/2) - childrenPos.height / 2}px`,
left: `${(childrenPos.x) - messagePos.width - 10}px`
});
} else if(position.toLowerCase() === "right"){
setStyle({
top: `${(+childrenPos.y + +messagePadding/2) - childrenPos.height / 2}px`,
left: `${+childrenPos.x + +childrenPos.width + 10}px`
});
} else {
// default bottom
setStyle({
top: `${(childrenPos.y) + childrenPos.height + 10}px`,
left: `${(childrenPos.x - messagePadding/2) - childrenPos.width / 2}px`
});
}
} else {
// default bottom position
setStyle({
top: `${(childrenPos.y) + childrenPos.height + 10}px`,
left: `${(childrenPos.x - messagePadding/2) - childrenPos.width / 2}px`
});
}
console.log("messagePos = ", messagePos);
console.log("messagePos = ", messagePadding);
console.log("childrenPos = ", childrenPos);
}, [classes]);
React.useEffect(() => {
setClasses(`popover ${isVisible ? "pop" : ""}`);
if (isVisible) {
resetVisibility();
}
}, [isVisible]);
return (
<div className="popover-component">
<span ref={childrenRef}>{children}</span>
<div className={classes} ref={popoverMessageRef} style={style}>
This is the popover
</div>
</div>
);
};
render(<App />, document.getElementById("root"));
.css:
.popover-component{
display: inline-block;
position: relative;
}
.popover{
display: none;
position: fixed; /* You can play with absolute position as well */
background-color: #797979;
border-radius: 4px;
padding: 5px;
}
.pop {
display: block; /* You can play with inline-block as well */
}
Here is the repro on stackblitz. You can then adjust the popover by getting the children's width and playing with it (like recreating the options "top", "bottom", "left", "right" by changing your algo).
Upvotes: 1