首页 > 解决方案 > 如何使 vuetify v-menu 项目可使用 tab 键导航

问题描述

我有一个 Vuetify 应用程序,它已经过可访问性审查 (WCAG 2.1 AA)。发现的问题之一是我的 v-app-bar 菜单无法使用 tab 键导航,只能使用箭头键导航。

目前,我的菜单是这样的:

  <v-menu offset-y>
    <template v-slot:activator="{ on }">
      <v-btn v-on="on" outlined>Menu one</v-btn>
    </template>
    <v-list>
      <v-list-item-group>
        <v-list-item>
          <v-list-item-title @click="menuclicked">Option one</v-list-item-title>
        </v-list-item>
        <v-list-item>
          <v-list-item-title>Option two</v-list-item-title>
        </v-list-item>
      </v-list-item-group>
    </v-list>
  </v-menu>

带有两个菜单的代码笔:https ://codepen.io/theocodepen/pen/QWMyRbr

但是,可访问性报告指出,一旦打开菜单,tab 键应该通过菜单项,而不是下一个菜单按钮。

因此,如果我单击“菜单一”,然后按选项卡,则应选择“选项一”,而不是“菜单二”(以及下一个选项卡上的“选项二”)。

到目前为止,我一直无法创造这种行为,有没有人知道如何做到这一点?

标签: vuetify.jsaccessibility

解决方案


我现在通过覆盖特定事件来实现它,给我所要求的行为:

对于菜单:

<v-menu ref="menuOne" offset-y>
  <template v-slot:activator="{ on, attrs }">
    <v-btn v-on:keydown.tab="menuTabPressed"
           v-on:click="on.click"
           v-on:keydown.enter="on.keydown"
           v-on:keydown.up="on.keydown"
           v-on:keydown.down="on.keydown"
           data-menu="menuOne"
           :v-bind="attrs"
           outlined>
      Menu one
    </v-btn>
  </template>
  <v-list>
    <!-- items go here -->

tab 键的事件处理函数:

menuTabPressed: function(event) {
  let menu = this.$refs[event.target.dataset.menu];
  // make sure children are evaluated
  menu.getTiles();
  // In most cases, we want the event to be stopped,
  // however, in the cases where we tab 'out of' the menu,
  // we want to propagate the event.
  let propagate = false;

  if (menu.isActive) {
      if (event.shiftKey) {
        if (menu.listIndex <= 0) {
          menu.isActive = false;
          propagate = true;
        } else {
          menu.prevTile();
        }
      } else {
        if (menu.listIndex < 0) {
          menu.firstTile();
        } else if (menu.listIndex + 1 >= menu.tiles.length) {
          menu.isActive = false;
          propagate = true;
        } else {
          menu.nextTile()
        }
      }
  } else {
    propagate = true;
  }
  if (!propagate) {
    event.preventDefault();
  }
},

带有完整示例的 Codepen:https ://codepen.io/theocodepen/pen/YzxWLLM


推荐阅读