mirror of
https://github.com/discourse/discourse.git
synced 2024-12-24 17:06:47 +08:00
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:
parent
d2d8fbcf3b
commit
3ddb1cfbad
|
@ -1,6 +1,9 @@
|
||||||
import Component from "@glimmer/component";
|
import Component from "@glimmer/component";
|
||||||
import { concat } from "@ember/helper";
|
import { concat } from "@ember/helper";
|
||||||
|
import { on } from "@ember/modifier";
|
||||||
|
import { action } from "@ember/object";
|
||||||
import { getOwner } from "@ember/owner";
|
import { getOwner } from "@ember/owner";
|
||||||
|
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||||
import { service } from "@ember/service";
|
import { service } from "@ember/service";
|
||||||
import { modifier } from "ember-modifier";
|
import { modifier } from "ember-modifier";
|
||||||
import { and } from "truth-helpers";
|
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() {
|
get menuId() {
|
||||||
return `d-menu-${this.menuInstance.id}`;
|
return `d-menu-${this.menuInstance.id}`;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +98,7 @@ export default class DMenu extends Component {
|
||||||
@translatedTitle={{@title}}
|
@translatedTitle={{@title}}
|
||||||
@disabled={{@disabled}}
|
@disabled={{@disabled}}
|
||||||
aria-expanded={{if this.menuInstance.expanded "true" "false"}}
|
aria-expanded={{if this.menuInstance.expanded "true" "false"}}
|
||||||
|
{{on "keydown" this.forwardTabToContent}}
|
||||||
...attributes
|
...attributes
|
||||||
>
|
>
|
||||||
{{#if (has-block "trigger")}}
|
{{#if (has-block "trigger")}}
|
||||||
|
@ -122,6 +148,7 @@ export default class DMenu extends Component {
|
||||||
@innerClass="fk-d-menu__inner-content"
|
@innerClass="fk-d-menu__inner-content"
|
||||||
@role="dialog"
|
@role="dialog"
|
||||||
@inline={{this.options.inline}}
|
@inline={{this.options.inline}}
|
||||||
|
{{didInsert this.registerFloatBody}}
|
||||||
>
|
>
|
||||||
{{#if (has-block)}}
|
{{#if (has-block)}}
|
||||||
{{yield this.componentArgs}}
|
{{yield this.componentArgs}}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user