You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

z-index值更高元素仍处于下层,hover删除按钮无响应原因排查

问题描述

鼠标hover左侧三点图标弹出absolute定位的「delete」按钮后,完全无法触发该按钮的交互;即使为按钮设置更高的z-index,问题依然存在,且弹窗与背景其他元素交互时也出现同样异常。项目中未使用sticky或fixed定位元素。

父组件相关代码

<Disclosure.Panel className="w-full text-gray-900 flex flex-col" >
        {projects?.map(project => Object.keys(project).map(key => (
          <div className={`w-4/5 py-2 hover:font-medium cursor-pointer self-end pl-2 flex items-center justify-between ${selectedProject === key ? 'bg-gray-900 text-gray-50 font-medium' : ''}`} onClick={() => handleSelect(key)} key={key}>
            <p>{key}</p>
            <Popover className='relative z-100'>
              <Popover.Button className='flex items-center'><EllipsisHorizontalIcon className='w-8 h-6 pr-2 hover:text-zinc-400'/></Popover.Button>
              <ProjectSettingsPopover selectedProject={selectedProject} />
            </Popover>
          </div>
        )))} 
        <div className="flex gap-2 h-7 mt-2 w-4/5 ml-auto">
          <input type='text' className='w-4/5 bg-background rounded-md px-2 py-1 text-sm border-2 border-grayDark' placeholder='New Project' value={input} onChange={(e) => setInput(e.target.value)}></input>
          <button className='bg-black p-1 rounded-full flex items-center justify-center hover:bg-zinc-700' onClick={() => handleNewProject()}><PlusCircleIcon className='text-primary h-5 w-5 group-hover:text-primaryDark'/></button>      
        </div>
</Disclosure.Panel>

ProjectSettingsPopover.js代码

return (
    <Transition
        enter="transition ease-out duration-200"
        enterFrom="opacity-0 -translate-x-1"
        enterTo="opacity-100 -translate-x-0"
        leave="transition ease-in duration-150"
        leaveFrom="opacity-100 -translate-x-0"
        leaveTo="opacity-0 -translate-x-1" 
        appear 
    >
        <Popover.Panel className="left-9 -top-8 w-24 text-sm z-50 rounded-sm flex flex-col absolute bg-background shadow-lg ring-1 border border-black ring-black ring-opacity-5">
            <Button btnStyle='default' btnSize='edgy' onClick={deleteProject}>delete</Button>
        </Popover.Panel>                    
    </Transition>
  )
问题原因
  • 父容器点击事件的冒泡干扰:包裹Popover的父div绑定了handleSelect点击事件,点击弹窗按钮时,事件会向上冒泡触发该父div的点击事件;而Headless UI的Popover默认会将父容器的点击判定为「外部点击」,直接关闭Popover.Panel,导致按钮交互还没触发就被中断。
  • 弹窗定位超出范围后的事件拦截:弹窗使用left-9 -top-8的absolute定位,视觉上跳出了父div的区域,若父div的上层容器存在隐式的overflow或事件捕获设置,会拦截弹窗的交互事件。
解决方案
  1. 阻止弹窗事件冒泡:在delete按钮的点击事件中阻止冒泡,避免触发父容器的点击事件:
<Button btnStyle='default' btnSize='edgy' onClick={(e) => {
  e.stopPropagation();
  deleteProject();
}}>delete</Button>
  1. 强制弹窗接收交互事件:给Popover.Panel添加pointer-events-auto类,确保弹窗自身能接收交互,避免被父元素的pointer-events设置覆盖:
<Popover.Panel className="left-9 -top-8 w-24 text-sm z-50 rounded-sm flex flex-col absolute bg-background shadow-lg ring-1 border border-black ring-black ring-opacity-5 pointer-events-auto">
  1. 调整Popover的DOM结构:将Popover从父div中移出,直接作为Disclosure.Panel的子元素,彻底规避父div的事件干扰:
// 父组件调整后的核心代码
<Disclosure.Panel className="w-full text-gray-900 flex flex-col" >
  {projects?.map(project => Object.keys(project).map(key => (
    <>
      <div className={`w-4/5 py-2 hover:font-medium cursor-pointer self-end pl-2 flex items-center justify-between ${selectedProject === key ? 'bg-gray-900 text-gray-50 font-medium' : ''}`} onClick={() => handleSelect(key)} key={key}>
        <p>{key}</p>
        <Popover.Button className='flex items-center'><EllipsisHorizontalIcon className='w-8 h-6 pr-2 hover:text-zinc-400'/></Popover.Button>
      </div>
      <Popover className='relative z-100'>
        <ProjectSettingsPopover selectedProject={selectedProject} />
      </Popover>
    </>
  ))} 
  {/* 其余代码保持不变 */}
</Disclosure.Panel>

内容的提问来源于stack exchange,提问作者rey2197

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:50:19