Reputation:
I'm building out a custom Tooltip
component in React that allows for rendering both to the right of the element as well as below it. I've decided to handle the functionality by having the Tooltip
accept children which it then renders, and when those children are hovered the tip itself, positioned absolutely, will become visible through CSS classes. The effect works exactly how I want when the elements are stacked in a column and the tooltip is set to render to the right, but when the elements are laid out in a row with the tip rendering on the bottom, the tip itself becomes misaligned from the child its rendering -- the length of the tooltip text seems to offset it to the right.
Here's a codesandbox displaying the problem. You'll see that in the first state, when the elements are in a column, the tip is aligned perfectly. Click the button to toggle them into a row format and hover again to see that they are now misaligned:
https://codesandbox.io/s/busted-tooltip-obf0h1?file=/src/Tooltip.scss
How can I get the tips to align centered with their child element when I've chosen to have them render below it?
// Tooltip.jsx
import React, { useState } from 'react';
import './Tooltip.scss';
const Tooltip = ({ children, label, orientation = 'right' }) => {
const [isHovered, setIsHovered] = useState(false);
return (
<div className={`Tooltip__Container ${orientation}`}>
<div
onMouseOver={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{children}
</div>
<div className={`Tooltip__Inner ${orientation} ${isHovered ? 'Visible' : ''}`}>
{orientation === 'right' && <div className={`Tooltip__PointLeft ${isHovered ? 'Visible' : ''}`} />}
{orientation === 'bottom' && <div className={`Tooltip__PointUp ${isHovered ? 'Visible' : ''}`} />}
<div className={`Tooltip ${orientation} ${isHovered ? 'Visible' : ''}`}>
{label}
</div>
</div>
</div>
);
};
export default Tooltip;
/* Tooltip.scss */
@import 'src/styles/colors.scss', 'src/styles/typography.scss', 'src/styles/breakpoints.scss';
.Tooltip__Container {
display: flex;
position: relative;
&.right {
flex-direction: row;
}
&.bottom {
flex-direction: column;
}
}
.Tooltip__Inner {
display: flex;
z-index: -1;
position: absolute;
transition: all .25s ease;
opacity: 0;
left: 0;
top: 0;
&.right {
flex-direction: row;
}
&.bottom {
flex-direction: column;
}
}
.Tooltip__Inner.right.Visible {
opacity: 1;
left: 3.5rem;
}
.Tooltip__Inner.bottom.Visible {
opacity: 1;
top: 3.5rem;
}
.Tooltip__PointLeft.Visible {
opacity: 1;
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-right: 10px solid $white-transparent;
align-self: center;
justify-self: center;
}
.Tooltip__PointUp.Visible {
opacity: 1;
width: 0;
height: 0;
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid $white-transparent;
align-self: center;
justify-self: center;
}
.Tooltip {
background-color: $white-transparent;
padding: .75rem;
border-radius: 3px;
@include MainFont;
color: white;
}
Upvotes: 0
Views: 148
Reputation: 41
For quick solution, you can update the bottom class inside .Tooltip__Inner
with this:
&.bottom {
flex-direction: column;
left: 50%;
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
Upvotes: 0