工具提示不会在滚动时消失



我在网站上有一个按钮和一个工具提示,它描述了按钮的操作。

但有一个错误我无法解决(我已经开始怀疑这个问题是否有解决方案(。

问题描述:当用户将鼠标悬停在图标上时,会出现一个工具提示-这里一切正常。但是,如果此时表正在滚动,则工具提示会飞出边界。很难描述,看看

滚动时请注意工具提示(如果光标悬停在上面(是如何向上或向下飞行的。

告诉我如何解决这个问题?

<div>
<Tooltip 
title="Delete" 
arrow
componentsProps={{
tooltip: {
sx: {
bgcolor: '#a3a3a3',
'& .MuiTooltip-arrow': {
color: '#a3a3a3',
},
},
},
}}
PopperProps={{
modifiers: [
{
name: "offset",
options: {
offset: [0, -8],
},
},
],
}}>
<DeleteForeverIcon/>
</Tooltip>
</div>

说明:将鼠标悬停在第一列中的任何单元格上,等待工具提示出现。然后向上或向下滚动滚轮,查看工具提示如何在表格之外显示

附言:请注意,这个问题已经回答了。原则上,这个解决方案是有效的。但是在将这个解决方案添加到我的真实代码中时,我遇到了很多问题。对我来说,一个简单的解决方案可能是当你把鼠标悬停在按钮上时,简单地取消滚动。告诉我如何做到这一点(但请记住,这个位置:在这种情况下固定是不合适的(

我的方法不同,每个工具提示都维护自己的状态。它使用IntersectionObserver来确定ToolTip组件是否可见。当组件不再可见时,它将通过PopperProps上的sx道具将CSS设置为display: 'none'来隐藏Popper(工具提示弹出窗口(。

Codesandbox示例:此处为

这是修改后的文件FileDownloadButton.jsx:

import React from "react";
import FileDownloadIcon from "@mui/icons-material/FileDownload";
import { ButtonGroup, Tooltip } from "@mui/material";
export default function FileDownloadButton() {
const tipRef = React.useRef(null);
const [inView, setInView] = React.useState(false);
const cb = (entries) => {
const [entry] = entries;
entry.isIntersecting ? setInView(true) : setInView(false);
};
React.useEffect(() => {
const options = {
root: null,
rootMargin: "0px"
};
const ref = tipRef.current;
const observer = new IntersectionObserver(cb, options);
if (ref) observer.observe(ref);
return () => {
if (ref) observer.unobserve(ref);
};
}, [tipRef]);
return (
<ButtonGroup>
<div>
<Tooltip
ref={tipRef}
title="Download record "
arrow
componentsProps={{
tooltip: {
sx: {
bgcolor: "#a3a3a3",
"& .MuiTooltip-arrow": {
color: "#a3a3a3"
}
}
}
}}
PopperProps={{
sx: { display: inView ? "block" : "none" },
modifiers: [
{
name: "offset",
options: {
offset: [0, -8]
}
}
]
}}
>
<FileDownloadIcon />
</Tooltip>
</div>
</ButtonGroup>
);
}

参考变更

更改1

export default function FileDownloadButton() {
const tipRef = React.useRef(null);
const [inView, setInView] = React.useState(false);
const cb = (entries) => {
const [entry] = entries;
entry.isIntersecting ? setInView(true) : setInView(false);
};
React.useEffect(() => {
const options = {
root: null,
rootMargin: "0px"
};
const ref = tipRef.current;
const observer = new IntersectionObserver(cb, options);
if (ref) observer.observe(ref);
return () => {
if (ref) observer.unobserve(ref);
};
}, [tipRef]);

更改2

PopperProps={{
sx: { display: inView ? "block" : "none" },

更新1

原始海报想要切换

Codesandbox示例

import React, { useState } from "react";
import FileDownloadIcon from "@mui/icons-material/FileDownload";
import { ButtonGroup, IconButton, Tooltip } from "@mui/material";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
import VisibilityIcon from "@mui/icons-material/Visibility";
export default function FileDownloadButton() {
const [click, setClick] = useState(true);
const tipRef = React.useRef(null);
const [inView, setInView] = React.useState(false);
const cb = (entries) => {
const [entry] = entries;
entry.isIntersecting ? setInView(true) : setInView(false);
};
React.useEffect(() => {
const options = {
root: null,
rootMargin: "0px"
};
const ref = tipRef.current;
const observer = new IntersectionObserver(cb, options);
if (ref) observer.observe(ref);
return () => {
if (ref) observer.unobserve(ref);
};
}, [tipRef]);
return (
<ButtonGroup>
<div>
<Tooltip
ref={tipRef}
title={click ? "Show item" : "Hide Item"}
arrow
componentsProps={{
tooltip: {
sx: {
bgcolor: "#a3a3a3",
"& .MuiTooltip-arrow": {
color: "#a3a3a3"
}
}
}
}}
PopperProps={{
sx: { display: inView ? "block" : "none" },
modifiers: [
{
name: "offset",
options: {
offset: [0, -8]
}
}
]
}}
>
<IconButton onClick={() => setClick(!click)}>
{click ? <VisibilityOffIcon /> : <VisibilityIcon />}
</IconButton>
</Tooltip>
</div>
</ButtonGroup>
);
}

我认为这是特定于浏览器的问题。当我检查给定的url(https://codesandbox.io/s/silly-grass-1lb3qw)在firefox浏览器中,它运行良好(但在chrome中没有(。后来发现,和最新版本以来的其他浏览器相比,在chrome中滚动元素时悬停的效果会有所不同。

我做了以下更改,使其在铬中工作。基本上,每当我们悬停任何项目时,材料工具提示都会添加到文档中。所以我所做的是,我附加了一个滚动事件,如果有任何材料工具提示元素存在,我只是简单地将其删除

DeviceTable.jsx

export default function DevicesTable() {
const tableRef = useRef();
function removeElementsByClass(className){
const elements = document.getElementsByClassName(className);
while(elements.length > 0){
elements[0].remove();
}
}
useEffect(() => {
if (tableRef.current) {
tableRef.current.addEventListener("scroll", (e) => {
// CLASS NAME OF THE TOOLTIP ATTACHED TO THE DOM. THERE ARE MULTIPLE CLASSES BUT I FOUND FOLLOWING CLASSNAME TO BE UNIQUE. PLEASE CROSS CHECK FROM YOUR END AS WELL.
//YOU CAN CHECK THIS BY PASSING open={true} attribute on <Tooltip> AND INSPECT DOM
removeElementsByClass("css-yk351k-MuiTooltip-tooltip")
});
}
return () => {
if(tableRef.current) {
tableRef.current.removeEventListener("scroll", ()=>{});
}
}
}, []);
return (
<TableContainer  className="TableContainerGridStyle">
<Table className="TableStyle">
<DevicesTableHeader />
// CHANGED LINE
<TableBody ref={tableRef} className="TableBodyStyle">
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
</TableBody>
</Table>
</TableContainer>
);
}

除此之外,我认为您可以使用其他替代方法,如followCursor,将位置相对属性设置为表单元格(TableCellStyle(或主体。但这些并不能完全解决问题。

由于您将Table组件作为props子级传递给StateLabel组件,因此为了显示/呈现,我们需要更新StateLabel组件以使用props.children

export default function StateLabel({children}) {
return <div>{children}</div>;
}

在铬中滚动时Div悬停不起作用

最新更新