如何在子菜单打开时保持表格行的Hover状态
问题:子菜单激活时保持表格行Hover效果
我有一个展示设备的表格,鼠标悬停表格行时整行变灰并显示操作按钮,点击按钮弹出子菜单,但光标移到子菜单上时,行的Hover灰色效果就消失了。怎么让子菜单激活(打开)时保持行的Hover样式?
相关代码
App.tsx
import "./styles.css"; import { SubMenu } from "./SubMenu"; const subMenuSlice = <SubMenu />; const nodes = [ { id: "0", name: "Samsung Galaxy", subMenu: subMenuSlice }, { id: "0", name: "Iphone", subMenu: subMenuSlice } ]; export default function App() { return ( <table> <tbody> {nodes.map((val, key) => ( <tr key={key}> <td>{val.name}</td> <td>{val.subMenu}</td> </tr> ))} </tbody> </table> ); }
SubMenu.tsx
import { useState } from "react"; import AppsIcon from "@mui/icons-material/Apps"; import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import "./styles.css"; export const SubMenu = () => { const [isOpen, setIsOpen] = useState(false); return ( <DropdownMenu.Root open={isOpen} onOpenChange={setIsOpen}> <DropdownMenu.Trigger> <AppsIcon className="sss" /> </DropdownMenu.Trigger> <DropdownMenu.Portal> <DropdownMenu.Content side="bottom" sideOffset={-30} align="start" alignOffset={80} > <button className="style-button">Edit </button> <button className="style-button">Make </button> <button className="style-button">Delete </button> </DropdownMenu.Content> </DropdownMenu.Portal> </DropdownMenu.Root> ); };
styles.css
.sss { visibility: hidden; } tr:hover .sss { background: gray; visibility: visible; } tr:hover { background: gray; visibility: visible; pointer-events: initial !important; } .style-button:hover { background-color: aqua; }
解决方案
核心思路是通过状态跟踪子菜单的打开状态,给对应表格行添加一个和Hover效果一致的CSS类,让菜单打开时行保持灰色样式。
1. 修改SubMenu组件,传递菜单状态给父组件
给SubMenu添加回调函数,把菜单的打开/关闭状态同步到父组件:
import { useState } from "react"; import AppsIcon from "@mui/icons-material/Apps"; import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import "./styles.css"; export const SubMenu = ({ onMenuOpen }: { onMenuOpen: (isOpen: boolean) => void }) => { const [isOpen, setIsOpen] = useState(false); const handleOpenChange = (open: boolean) => { setIsOpen(open); onMenuOpen(open); // 将状态传递给父组件 }; return ( <DropdownMenu.Root open={isOpen} onOpenChange={handleOpenChange}> <DropdownMenu.Trigger> <AppsIcon className="sss" /> </DropdownMenu.Trigger> <DropdownMenu.Portal> <DropdownMenu.Content side="bottom" sideOffset={-30} align="start" alignOffset={80} > <button className="style-button">Edit </button> <button className="style-button">Make </button> <button className="style-button">Delete </button> </DropdownMenu.Content> </DropdownMenu.Portal> </DropdownMenu.Root> ); };
2. 在父组件中跟踪每行的菜单状态,添加动态类
在App组件中用state存储每行的菜单打开状态,给对应表格行添加row-active类:
import "./styles.css"; import { SubMenu } from "./SubMenu"; import { useState } from "react"; export default function App() { const [menuOpenStates, setMenuOpenStates] = useState<Record<number, boolean>>({}); const handleMenuOpen = (key: number, isOpen: boolean) => { setMenuOpenStates(prev => ({ ...prev, [key]: isOpen })); }; const nodes = [ { id: "0", name: "Samsung Galaxy" }, { id: "0", name: "Iphone" } ]; return ( <table> <tbody> {nodes.map((val, key) => ( <tr key={key} className={menuOpenStates[key] ? "row-active" : ""} > <td>{val.name}</td> <td> <SubMenu onMenuOpen={(isOpen) => handleMenuOpen(key, isOpen)} /> </td> </tr> ))} </tbody> </table> ); }
3. 修改CSS,让row-active类继承Hover样式
更新styles.css,让row-active类的效果和tr:hover完全一致:
.sss { visibility: hidden; } tr:hover .sss, tr.row-active .sss { background: gray; visibility: visible; } tr:hover, tr.row-active { background: gray; visibility: visible; pointer-events: initial !important; } .style-button:hover { background-color: aqua; }
这样当子菜单打开时,对应的表格行会自动加上row-active类,保持和鼠标悬停时一样的灰色样式,直到菜单关闭为止。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

