焦点陷阱 <dialog> 不是绝对的,焦点转移到浏览器 UI 元素

Focus trap on <dialog> not absolute, focus escapes to browser UI elements

我正在努力了解 <dialog> html 元素和示例 laid out by MDN here.

当我 运行 从中提取代码时...

var updateButton = document.getElementById('updateDetails');
var favDialog = document.getElementById('favDialog');
var outputBox = document.querySelector('output');
var selectEl = document.querySelector('select');
var confirmBtn = document.getElementById('confirmBtn');

// "Update details" button opens the <dialog> modally
updateButton.addEventListener('click', function onOpen() {
  if (typeof favDialog.showModal === "function") {
    favDialog.showModal();
  } else {
    alert("The <dialog> API is not supported by this browser");
  }
});
// "Favorite animal" input sets the value of the submit button
selectEl.addEventListener('change', function onSelect(e) {
  confirmBtn.value = selectEl.value;
});
// "Confirm" button of form triggers "close" on dialog because of [method="dialog"]
favDialog.addEventListener('close', function onClose() {
  outputBox.value = favDialog.returnValue + " button clicked - " + (new Date()).toString();
});
<!-- Simple pop-up dialog box containing a form -->
<dialog id="favDialog">
  <form method="dialog">
    <p><label>Favorite animal:
      <select>
        <option></option>
        <option>Brine shrimp</option>
        <option>Red panda</option>
        <option>Spider monkey</option>
      </select>
    </label></p>
    <menu>
      <button value="cancel">Cancel</button>
      <button id="confirmBtn" value="default">Confirm</button>
    </menu>
  </form>
</dialog>

<menu>
  <button id="updateDetails">Update details</button>
</menu>

<output aria-live="polite"></output>

...我发现当对话框打开时,焦点并不像 ARIA modal example 描述的那样完全“陷入”。他们说当用户按下 tab 键时:

When focus is on the last focusable element in the dialog, moves focus to the first focusable element in the dialog.

但是,对话框元素的 MDN 示例允许用户“跳出”模式并进入浏览器框架。在我的例子中,使用 chrome,在确认按钮按下 tab 后将聚焦“查看站点信息”按钮,然后是文档区域之外的地址栏。

这是怎么回事。 MDN 的例子不完整吗? Web 开发人员是否需要编写额外的 JS 代码来真正聚焦陷阱,以便在生产中使用 <dialog> 元素?或者从可访问性的角度来看,允许模式部分捕获焦点是否是“可接受的”,如示例中那样,选项卡上的按键可以暂时转义到浏览器 UI 元素。

I find that when the dialog opens the focus does not completely "trap" like the ARIA modal example describes.

那是因为 W3 指南上的示例确实有 custom javascript 来捕获在对话框上使用焦点。您可以看到评论中也提到了相同的内容:

...

// Bracket the dialog node with two invisible, focusable nodes.
// While this dialog is open, we use these to make sure that focus never
// leaves the document even if dialogNode is the first or last node.
var preDiv = document.createElement('div');
this.preNode = this.dialogNode.parentNode.insertBefore(preDiv, this.dialogNode);
this.preNode.tabIndex = 0;
var postDiv = document.createElement('div');
this.postNode = this.dialogNode.parentNode.insertBefore(postDiv, this.dialogNode.nextSibling);
this.postNode.tabIndex = 0;

...

What's going on here. Is MDN's example incomplete?

我不会说它不完整,但两个指南都针对不同的受众,您提到的 w3 文档是可访问性指南,而 MDN 文档只是描述 dialog HTML 规格

Would a web developer need to write additional JS code to truly focus trap in order to use the element in production? Or is it "acceptable" from an accessibility perspective to allow a modal to partially trap the focus as in the example, where the keypress on tab can temporarily escape to browser UI elements.

我想这取决于您和您的产品用户。大多数情况下,从可访问性的角度来看,建议将用户焦点限制在对话框中,并允许通过转义键、关闭按钮和取消按钮关闭对话框。

是的,您必须在 javascript 或 HTML 中添加鼠标捕获的自定义代码,方法是添加 2 个可聚焦元素,如您在辅助功能指南页面上的示例中所见提到了。

我只是在 div 标签中添加了对话框,它起作用了。

示例代码:

 <div>
   <Transition.Root show={true} as={Fragment}>
     <Dialog as="div">
       <Transition.Child></Transition.Child>
     </Dialog as="div"> 
   </Transition.Root show={true} as={Fragment}>  
</div>