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

如何通过Tab键聚焦Material UI Autocomplete自定义Popper内的按钮

解决Material UI Autocomplete自定义按钮的键盘可访问性问题

要让自定义Popper中的按钮能通过Tab键正常访问且不关闭Autocomplete弹窗,需要手动控制弹窗的打开状态,并阻止Tab事件的默认传播行为,具体实现如下:

步骤1:引入状态管理弹窗打开状态

使用useState维护Autocomplete的打开状态,从而手动控制弹窗的显示与隐藏:

import { useState } from 'react';
// ...其他组件导入

步骤2:修改Autocomplete组件,绑定状态与事件

将状态绑定到Autocomplete的open属性,通过onOpen和onClose控制状态变化,同时调整事件逻辑确保焦点在按钮上时弹窗保持打开:

export default function ComboBox() {
  const [open, setOpen] = useState(false);
  const handleNotFound = () => {
    alert("Not found");
  };

  return (
    <Autocomplete
      disablePortal
      id="combo-box-demo"
      options={top100Films}
      sx={{ width: 300 }}
      renderInput={(params) => <TextField {...params} label="Movie" />}
      PopperComponent={(props) => (
        <Popper {...props} placement="bottom">
          {props.children}
          <div style={{ padding: '8px', borderTop: '1px solid #e0e0e0' }}>
            <Button
              type="button"
              tabIndex={0}
              fullWidth
              onMouseDown={handleNotFound}
              onKeyDown={(e) => {
                // 阻止Tab事件冒泡,避免Autocomplete触发弹窗关闭
                if (e.key === 'Tab') {
                  e.stopPropagation();
                }
                // 按下Escape时关闭弹窗,保持通用交互逻辑
                if (e.key === 'Escape') {
                  setOpen(false);
                }
              }}
              onBlur={() => {
                // 焦点完全离开Autocomplete组件时关闭弹窗
                setTimeout(() => {
                  const autocompleteElement = document.getElementById('combo-box-demo');
                  if (!autocompleteElement?.contains(document.activeElement)) {
                    setOpen(false);
                  }
                }, 0);
              }}
            >
              I don't see my movie
            </Button>
          </div>
        </Popper>
      )}
      open={open}
      onOpen={() => setOpen(true)}
      onClose={(event, reason) => {
        // 仅当焦点不在自定义按钮上时,允许关闭弹窗
        const activeElement = document.activeElement;
        if (!activeElement?.textContent.includes("I don't see my movie")) {
          setOpen(false);
        }
      }}
    />
  );
}

关键逻辑说明

  • 阻止Tab事件冒泡:在按钮的onKeyDown事件中拦截Tab键事件,避免Autocomplete的默认键盘逻辑触发弹窗关闭。
  • 手动控制弹窗状态:通过useState管理弹窗的打开/关闭,确保焦点停留在按钮上时弹窗保持显示。
  • 焦点离开时关闭弹窗:按钮失去焦点后,延迟检查当前焦点是否仍在Autocomplete组件内部,若完全离开则关闭弹窗,保证交互合理性。
  • Escape键一致性:保留Escape键关闭弹窗的默认行为,符合用户通用交互预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 14:23:28