Reputation: 197
There is a table on one of the pages of the site. Some table cells have icons (from mui) with a tooltip. When you hover over the icon, a tooltip appears.
Here a problem arises: if the tooltip is open and the table is scrolled, then the tooltip flies out of the table borders.
Below is the code with the cell that contains the icon
export default function TableCell() {
return (
<TableRow className="TableCellStyle">
<TableCell>
<Tooltip
title="Download"
arrow
componentsProps={{
tooltip: {
sx: {
bgcolor: "#a3a3a3",
"& .MuiTooltip-arrow": {
color: "#a3a3a3"
}
}
}
}}
PopperProps={{
modifiers: [
{
name: "offset",
options: {
offset: [0, -8]
}
}
]
}}
>
<FileDownloadIcon />
</Tooltip>
</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
</TableRow>
);
}
Tell me how to make the tooltip disappear if the table scrolls
Update: so far there was an answer that when hovering over the tooltip, the scrolling of the table would disappear altogether. But that doesn't quite work for me. I would like the tooltip to disappear as soon as the scroll starts.
Upvotes: 1
Views: 2196
Reputation: 1655
Import useEffect()
from React and add this function to the FileDownloadButton.jsx component:
useEffect(() => {
const scrollableElements = [
document.querySelector(".TableBodyStyle"),
document
];
scrollableElements.forEach((element) => {
element.addEventListener("scroll", (event) => {
const tooltip = document.querySelector("[role='tooltip']");
if (tooltip) {
tooltip.style.display = "none";
}
});
});
});
What we're doing is checking to see if the tooltip is visible, and if it is, we're setting the display to none when the table is scrolled.
A cleaner way would be to call the Tooltip's inbuilt hide function, that way you would retain the hiding animation. I've not used React before though, so I'm unsure of how to programmatically call the functions of a child component. If you know how to do that, you can substitute the code inside the listener with that function call instead.
Here's what the current method looks like: https://codesandbox.io/s/festive-ritchie-f9jizd?file=/src/FileDownloadButton.jsx
So I did a bit of reading and was able to figure out how to solve this issue using react state. It is almost the same as above, we just need to create a state variable and setter function, and call the setter inside the eventHandler.
This is what it'll look like:
const [showTooltip, setShowTooltip] = useState(false);
useEffect(() => {
const scrollableElements = [
document.querySelector(".TableBodyStyle"),
document
];
scrollableElements.forEach((element) => {
element.addEventListener("scroll", (event) => {
setShowTooltip(false)
});
});
});
For this method you will also need to pass these values as props to the Tooltip component.
<Tooltip
title="Show item"
arrow
open={showTooltip}
onOpen={()=> { setShowTooltip(true) }}
onClose={()=> { setShowTooltip(false) }}
componentsProps={{
tooltip: {
sx: {
bgcolor: "#a3a3a3",
"& .MuiTooltip-arrow": {
color: "#a3a3a3"
}
}
}
}}
PopperProps={{
modifiers: [
{
name: "offset",
options: {
offset: [0, -8]
}
}
]
}}
>
This is what the new method would look like: https://codesandbox.io/s/hide-tooltip-using-react-6ctu7y?file=/src/FileDownloadButton.jsx
Upvotes: 1
Reputation: 181
Here is one possible solution:
Strategy: Use a state variable to define when you want the table body to be scroll-able and when not to. On enter and exit of hover you can toggle the state and apply conditional styling to html.
Sandbox link: https://codesandbox.io/s/confident-margulis-25h1gh?file=/src/DevicesTableCell.jsx
Code:
export default function DevicesTableCell({ setAllowScroll }) {
return (
<TableRow className="TableCellStyle">
<TableCell>
<Tooltip
title="Download item"
arrow
onOpen={() => {
setAllowScroll(false);
}}
onClose={() => {
setAllowScroll(true);
}}
componentsProps={{
tooltip: {
sx: {
bgcolor: "#a3a3a3",
"& .MuiTooltip-arrow": {
color: "#a3a3a3"
}
}
}
}}
PopperProps={{
modifiers: [
{
name: "offset",
options: {
offset: [0, -8]
}
}
]
}}
>
<FileDownloadIcon />
</Tooltip>
</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
<TableCell>Some Text</TableCell>
</TableRow>
);
}
export default function DevicesTable() {
const [allowScroll, setAllowScroll] = useState(true);
return (
<TableContainer className="TableContainerGridStyle">
<Table className="TableStyle">
<DevicesTableHeader />
<TableBody
className="TableBodyStyle"
style={!allowScroll ? { overflow: "hidden" } : {}}
>
<DevicesTableCell setAllowScroll={setAllowScroll} />
<DevicesTableCell setAllowScroll={setAllowScroll} />
<DevicesTableCell setAllowScroll={setAllowScroll} />
<DevicesTableCell setAllowScroll={setAllowScroll} />
<DevicesTableCell setAllowScroll={setAllowScroll} />
<DevicesTableCell setAllowScroll={setAllowScroll} />
<DevicesTableCell setAllowScroll={setAllowScroll} />
<DevicesTableCell setAllowScroll={setAllowScroll} />
<DevicesTableCell setAllowScroll={setAllowScroll} />
<DevicesTableCell setAllowScroll={setAllowScroll} />
</TableBody>
</Table>
</TableContainer>
);
}
Upvotes: 1