Skip to content

Commit

Permalink
Merge pull request #24 from tableflowhq/fix/tooltip
Browse files Browse the repository at this point in the history
Changed tooltip to use react portal
  • Loading branch information
ciminelli authored Sep 26, 2023
2 parents 4b882f0 + 8ba6282 commit e18c7db
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 42 deletions.
44 changes: 42 additions & 2 deletions src/Tooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useEffect, useRef, useState } from "react";
import ReactDOM from "react-dom";
import classes from "../utils/classes";
import getStringLengthOfChildren from "../utils/getStringLengthOfChildren";
import { AsMap, TooltipProps } from "./types";
Expand All @@ -10,12 +12,50 @@ export default function Tooltip<T extends keyof AsMap>({ as, className, title, c
const length = getStringLengthOfChildren(title);
const wrapperClasses = classes([style.tooltip, className, length > 30 && style.multiline]);

const [tooltipVisible, setTooltipVisible] = useState(false);
const [position, setPosition] = useState({ top: 0, left: 0 });
const targetRef = useRef<any>(null);

// Create a ref to attach the tooltip portal to
const tooltipContainer = useRef(document.createElement("div"));

useEffect(() => {
// Appending the tooltip container to the body on mount
document.body.appendChild(tooltipContainer.current);

// Removing the tooltip container from the body on unmount
return () => {
document.body.removeChild(tooltipContainer.current);
};
}, []);

const showTooltip = () => {
if (targetRef.current) {
const rect = targetRef.current.getBoundingClientRect();
setPosition({
top: rect.bottom + window.scrollY,
left: rect.left + rect.width / 2 + window.scrollX,
});
setTooltipVisible(true);
}
};

const hideTooltip = () => {
setTooltipVisible(false);
};

const tooltipMessage = tooltipVisible && (
<span className={style.message} style={{ position: "fixed", top: `${position.top}px`, left: `${position.left}px` }}>
{title}
</span>
);

return (
<Tag {...props} className={wrapperClasses}>
{children}
<span className={style.icon}>
<span className={style.icon} onMouseEnter={showTooltip} onMouseLeave={hideTooltip} ref={targetRef}>
<Icon icon={icon} />
<span className={style.message}>{title}</span>
{ReactDOM.createPortal(tooltipMessage, tooltipContainer.current)}
</span>
</Tag>
);
Expand Down
72 changes: 32 additions & 40 deletions src/Tooltip/style/Tooltip.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,49 @@ $height: calc($side * 1.732);

.icon {
position: relative;
display: block;

svg {
display: block;
cursor: pointer;
}
}

&:hover,
&:active {
.message {
display: block;
}
}
&.multiline .message {
width: 260px;
white-space: normal;
}
}


.message {
position: absolute;
transform: translateX(-50%);
background-color: var(--color-background-modal);
z-index: 3;
padding: var(--m-xxs) var(--m-xs);
border-radius: var(--border-radius);
margin-top: var(--m-xs);
box-shadow: 0 0 0 1px var(--color-border), 0 5px 15px rgba(0, 0, 0, 0.2);
white-space: nowrap;

.message {
&::after,
&::before {
position: absolute;
top: 100%;
top: calc($height * -1);
left: 50%;
border-left: $side solid transparent;
border-right: $side solid transparent;
border-bottom: $height solid var(--color-border);
content: "";
font-size: 0;
line-height: 0;
width: 0;
transform: translateX(-50%);
background-color: var(--color-background-modal);
z-index: 3;
padding: var(--m-xxs) var(--m-xs);
border-radius: var(--border-radius);
display: none;
margin-top: var(--m-xs);
box-shadow: 0 0 0 1px var(--color-border), 0 5px 15px rgba(0, 0, 0, 0.2);
white-space: nowrap;

&::after,
&::before {
position: absolute;
top: calc($height * -1);
left: 50%;
border-left: $side solid transparent;
border-right: $side solid transparent;
border-bottom: $height solid var(--color-border);
content: "";
font-size: 0;
line-height: 0;
width: 0;
transform: translateX(-50%);
}

&::after {
top: calc($height * -1 + 2px);
border-bottom: $height solid var(--color-background-modal);
}
}

&.multiline .message {
width: 260px;
white-space: normal;
&::after {
top: calc($height * -1 + 2px);
border-bottom: $height solid var(--color-background-modal);
}
}
}

0 comments on commit e18c7db

Please sign in to comment.