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.
This commit is contained in:
Joffrey JAFFEUX
2024-12-04 12:46:02 +01:00
committed by GitHub
parent d2d8fbcf3b
commit 3ddb1cfbad

View File

@ -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}}