From 3ddb1cfbad4c9d2238ab0665ff350b7d0f22bcf8 Mon Sep 17 00:00:00 2001 From: Joffrey JAFFEUX Date: Wed, 4 Dec 2024 12:46:02 +0100 Subject: [PATCH] FIX: ensures tabbing from trigger focus content (#30064) `DMenu` is using in-element, which means the content is detached from the trigger, and pressing tab from the trigger is not going to jump into the content. This commit catches the tab event and attempts to focus the first focusable element of the content. --- .../float-kit/addon/components/d-menu.gjs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app/assets/javascripts/float-kit/addon/components/d-menu.gjs b/app/assets/javascripts/float-kit/addon/components/d-menu.gjs index d2d3a4748f9..e6d82597d00 100644 --- a/app/assets/javascripts/float-kit/addon/components/d-menu.gjs +++ b/app/assets/javascripts/float-kit/addon/components/d-menu.gjs @@ -1,6 +1,9 @@ import Component from "@glimmer/component"; import { concat } from "@ember/helper"; +import { on } from "@ember/modifier"; +import { action } from "@ember/object"; import { getOwner } from "@ember/owner"; +import didInsert from "@ember/render-modifiers/modifiers/did-insert"; import { service } from "@ember/service"; import { modifier } from "ember-modifier"; import { and } from "truth-helpers"; @@ -31,6 +34,28 @@ export default class DMenu extends Component { }; }); + @action + registerFloatBody(element) { + this.body = element; + } + + @action + forwardTabToContent(event) { + if (!this.body) { + return; + } + + if (event.key === "Tab") { + event.preventDefault(); + + const firstFocusable = this.body.querySelector( + 'button, a, input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"])' + ); + + firstFocusable?.focus() || this.body.focus(); + } + } + get menuId() { return `d-menu-${this.menuInstance.id}`; } @@ -73,6 +98,7 @@ export default class DMenu extends Component { @translatedTitle={{@title}} @disabled={{@disabled}} aria-expanded={{if this.menuInstance.expanded "true" "false"}} + {{on "keydown" this.forwardTabToContent}} ...attributes > {{#if (has-block "trigger")}} @@ -122,6 +148,7 @@ export default class DMenu extends Component { @innerClass="fk-d-menu__inner-content" @role="dialog" @inline={{this.options.inline}} + {{didInsert this.registerFloatBody}} > {{#if (has-block)}} {{yield this.componentArgs}}