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

如何让PrimeReact弹出菜单支持键盘Tab导航与aria-labels功能?

问题描述

按下按钮的Enter键打开弹出菜单后,无法使用Tab键遍历菜单选项,期望实现Tab键遍历并选择合适选项。

现有代码

import { Button } from 'primereact/button';
import { Menu } from 'primereact/menu';

function Header() {
  const [menu, setMenu] = useState('');
  const testModelItems = [{label: 'Menu', items: [{label: 'Main 1'}, {label: 'Option 2'}]}];

  return (
    <div className={'menu-button-div'}>
      <Menu model={testModelItems} popup ref={(e) => setMenu(e)} id={'menu'} aria-labelledby={'menu-dropdown'}/>
      <Button aria-expanded={false} aria-labelledby={'menu-dropdown'} aria-controls={'menu'} aria-haspopup label={'Main Menu'} onClick={(e) => menu.toggle(e)}/>
    </div>
  )
}

解决方案

关键调整点

  1. 绑定菜单展开状态到aria-expanded,符合无障碍交互标准
  2. 菜单弹出后手动管理菜单项的tabindex,允许Tab键聚焦
  3. 自动聚焦首个菜单项,确保键盘交互的连贯性

修改后代码

import { useState } from 'react';
import { Button } from 'primereact/button';
import { Menu } from 'primereact/menu';

function Header() {
  const [menu, setMenu] = useState(null);
  const [menuVisible, setMenuVisible] = useState(false);
  const testModelItems = [{label: 'Menu', items: [{label: 'Main 1'}, {label: 'Option 2'}]}];

  const handleMenuShow = () => {
    setMenuVisible(true);
    // 菜单弹出后,设置所有菜单项可被Tab聚焦,并自动聚焦首个选项
    setTimeout(() => {
      const menuItems = document.querySelectorAll('#menu .p-menuitem-link');
      if (menuItems.length > 0) {
        menuItems.forEach(item => item.setAttribute('tabindex', '0'));
        menuItems[0].focus();
      }
    }, 0);
  };

  const handleMenuHide = () => {
    setMenuVisible(false);
    // 菜单关闭后恢复菜单项的tabindex,避免干扰其他交互
    const menuItems = document.querySelectorAll('#menu .p-menuitem-link');
    menuItems.forEach(item => item.setAttribute('tabindex', '-1'));
  };

  return (
    <div className={'menu-button-div'}>
      <Menu 
        model={testModelItems} 
        popup 
        ref={(e) => setMenu(e)} 
        id={'menu'} 
        aria-labelledby={'menu-dropdown'}
        onShow={handleMenuShow}
        onHide={handleMenuHide}
      />
      <Button 
        aria-expanded={menuVisible} 
        aria-labelledby={'menu-dropdown'} 
        aria-controls={'menu'} 
        aria-haspopup="true"
        label={'Main Menu'} 
        onClick={(e) => menu.toggle(e)}
      />
    </div>
  )
}

补充说明

通用的无障碍菜单交互规范中,弹出菜单默认用上下箭头键遍历选项,Tab键用于退出菜单回到触发按钮。如果坚持使用Tab遍历,上述修改可实现需求,但建议优先遵循标准交互模式,提升用户体验一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:25:31