我在网站上有一个按钮和一个ToolTip,它描述了按钮的动作。
但是有一个错误我解决不了(我已经开始怀疑这个问题是否有解决办法)。
问题描述:当用户悬停在图标上时,就会出现一个工具提示--这里的一切都很好。但是,如果此时表正在滚动,那么工具提示就会超出界限。很难形容,看看
注意在滚动时工具提示(如果光标悬浮在上面)是如何向上或向下的。
告诉我如何解决这个问题?
<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>
说明:悬停在第一列的任何单元格上,等待工具提示出现。然后向上或向下滚动滚轮,看看工具提示是如何在表外运行的。
附注:请注意,这个问题已经回答了。原则上,这个解决方案是可行的。但是当我将这个解决方案添加到我的实际代码中时,我遇到了很多问题。对我来说,一个简单的解决方案可能是,当你悬停在按钮上时,简单地取消滚动。告诉我如何做到这一点(但是请记住这个位置:在这种情况下固定是不合适的)
发布于 2022-10-19 22:34:13
我的方法是不同的,每个工具提示都维护自己的状态。它使用IntersectionObserver
来确定ToolTip
组件是否是可查看的。当组件不再可查看时,它将通过将Popper
设置为display: 'none'
,从而隐藏sx
(工具提示弹出)。
代码框示例:这里
以下是修改后的文件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
原版海报要切换
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>
);
}
发布于 2022-10-16 17:50:48
我认为这是浏览器特有的问题。当我在firefox中检查给定的url( https://codesandbox.io/s/silly-grass-1lb3qw)时,它运行得很好(但在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)或主体。但这些并不能完全解决问题。
当您将表组件作为道具传递给StateLabel组件时,为了显示/呈现,我们需要更新StateLabel组件以使用props.children
export default function StateLabel({children}) {
return <div>{children}</div>;
}
https://stackoverflow.com/questions/74079308
复制相似问题