I want to show/hide an Edit button based on hover status of table row. So I use useHover hooks from this website which the implementation is like this :
function useHover() {
const [value, setValue] = useState(false);
const ref = useRef(null);
const handleMouseOver = () => setValue(true);
const handleMouseOut = () => setValue(false);
useEffect(
() => {
const node = ref.current;
if (node) {
node.addEventListener("mouseover", handleMouseOver);
node.addEventListener("mouseout", handleMouseOut);
return () => {
node.removeEventListener("mouseover", handleMouseOver);
node.removeEventListener("mouseout", handleMouseOut);
};
}
},
[ref.current] // Recall only if ref changes
);
return [ref, value];
}
So currently my component structure roughly like this (just following the example from their docs):
function Row(props) {
const [hoverRef, isHovered] = useHover();
return (
<>
{/* attach the hoverRef in this TableRow */}
<TableRow ref={hoverRef}>
<TableCell>Simplified Info here</TableCell>
{/* I want this Edit button only displayed when someone hover the row and its 'child' group*/}
<div className={clsx(!isHovered && { visibility: "hidden" })}>
<IconButton>
<EditIcon />
</IconButton>
</div>
</TableRow>
{props.details.map((detail) => (
<TableRow>
<TableCell>
<Collapse>
<Text>Detailed information Here</Text>
{/* I also want to display this if the parent is hovered or this cell is hovered */}
<div className={clsx(!isHovered && { visibility: "hidden" })}>
<IconButton>
<EditIcon />
</IconButton>
</div>
</Collapse>
</TableCell>
</TableRow>
))}
</>
);
}
It is not fully work as I expect (Show Edit button on hover) since it only display edit button if only if the user hover their mouse over the <TableRow>Simplified Info</TableRow> Row. Want I want to do is to make both edit buttons also displayed for 2 cases:
- the user mouse is hovering the 'parent' row
- the user mouse is hovering one of its 'child' row
So I change the structure by wrapping the <TableRow> inside a div and attach the hover ref into that div like this:
function Row() {
const [hoverRef, isHovered] = useHover();
return (
<>
{/* Now adding div and attach the hoverRef into this div */}
<div ref={hoverRef}>
<TableRow ref={hoverRef}>
<TableCell>Simplified Info here</TableCell>
{/* Now this edit button also displayed even if the mouse is on top of its children*/}
<div className={clsx(!isHovered && { visibility: "hidden" })}>
<IconButton>
<EditIcon />
</IconButton>
</div>
</TableRow>
{props.details.map((detail) => (
<TableRow>
<TableCell>
<Collapse>
<Text>Detailed information Here</Text>
{/* This button also displayed even if the mouse is hovering its parent */}
<div className={clsx(!isHovered && { visibility: "hidden" })}>
<IconButton>
<EditIcon />
</IconButton>
</div>
</Collapse>
</TableCell>
</TableRow>
))}
</div>
</>
);
}
Yes it works but it breaks the style.
Here is some illustration that might help you to understand what I want to achieve (the group of row should be highlighted & edit buttons should be displayed) :

So The question is: Is there any advice on how to 'listen' to hover state of the parent and its children / siblings without breaking the style ?