diff --git a/app/assets/javascripts/discourse/app/components/notifications-tracking.gjs b/app/assets/javascripts/discourse/app/components/notifications-tracking.gjs
index ac803db2337..4ac1ba103cf 100644
--- a/app/assets/javascripts/discourse/app/components/notifications-tracking.gjs
+++ b/app/assets/javascripts/discourse/app/components/notifications-tracking.gjs
@@ -64,7 +64,7 @@ export default class NotificationsTracking extends Component {
@action
async setNotificationLevel(level) {
- await this.dmenuApi.close();
+ await this.dmenuApi.close({ focusTrigger: true });
this.args.onChange?.(level);
}
diff --git a/app/assets/javascripts/discourse/tests/integration/components/float-kit/d-menu-test.js b/app/assets/javascripts/discourse/tests/integration/components/float-kit/d-menu-test.js
index 7fdc9c2e7d1..dc9be4dd8e8 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/float-kit/d-menu-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/float-kit/d-menu-test.js
@@ -350,4 +350,43 @@ module("Integration | Component | FloatKit | d-menu", function (hooks) {
assert.dom(".fk-d-menu__trigger.first").doesNotExist();
assert.dom(".fk-d-menu.first").exists();
});
+
+ test("focusTrigger on close", async function (assert) {
+ this.api = null;
+ this.onRegisterApi = (api) => (this.api = api);
+ this.close = async () => await this.api.close();
+
+ await render(
+ hbs`
+
+ `
+ );
+
+ await click(".fk-d-menu__trigger");
+ await triggerKeyEvent(document.activeElement, "keydown", "Tab");
+ await triggerKeyEvent(document.activeElement, "keydown", "Enter");
+
+ assert.strictEqual(
+ document.activeElement,
+ document.querySelector(".fk-d-menu__trigger")
+ );
+ });
+
+ test("focusTrigger=false on close", async function (assert) {
+ this.api = null;
+ this.onRegisterApi = (api) => (this.api = api);
+ this.close = async () => await this.api.close({ focusTrigger: false });
+
+ await render(
+ hbs`
+
+ `
+ );
+
+ await click(".fk-d-menu__trigger");
+ await triggerKeyEvent(document.activeElement, "keydown", "Tab");
+ await triggerKeyEvent(document.activeElement, "keydown", "Enter");
+
+ assert.strictEqual(document.activeElement, document.body);
+ });
});
diff --git a/app/assets/javascripts/float-kit/addon/components/d-float-body.gjs b/app/assets/javascripts/float-kit/addon/components/d-float-body.gjs
index e0e826bf590..bb344a4228b 100644
--- a/app/assets/javascripts/float-kit/addon/components/d-float-body.gjs
+++ b/app/assets/javascripts/float-kit/addon/components/d-float-body.gjs
@@ -1,5 +1,5 @@
import Component from "@glimmer/component";
-import { concat, hash } from "@ember/helper";
+import { concat, fn, hash } from "@ember/helper";
import { htmlSafe } from "@ember/template";
import { modifier as modifierFn } from "ember-modifier";
import concatClass from "discourse/helpers/concat-class";
@@ -70,7 +70,9 @@ export default class DFloatBody extends Component {
{{(if
this.supportsCloseOnClickOutside
(modifier
- closeOnClickOutside @instance.close (hash target=this.content)
+ closeOnClickOutside
+ (fn @instance.close (hash focusTrigger=false))
+ (hash target=this.content)
)
)}}
{{(if
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 7f64042215c..4cbbf092576 100644
--- a/app/assets/javascripts/float-kit/addon/components/d-menu.gjs
+++ b/app/assets/javascripts/float-kit/addon/components/d-menu.gjs
@@ -4,6 +4,7 @@ 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 willDestroy from "@ember/render-modifiers/modifiers/will-destroy";
import { service } from "@ember/service";
import { modifier } from "ember-modifier";
import { and } from "truth-helpers";
@@ -39,6 +40,11 @@ export default class DMenu extends Component {
this.body = element;
}
+ @action
+ teardownFloatBody() {
+ this.body = null;
+ }
+
@action
forwardTabToContent(event) {
if (!this.body) {
@@ -151,6 +157,7 @@ export default class DMenu extends Component {
@role="dialog"
@inline={{this.options.inline}}
{{didInsert this.registerFloatBody}}
+ {{willDestroy this.teardownFloatBody}}
>
{{#if (has-block)}}
{{yield this.componentArgs}}
diff --git a/app/assets/javascripts/float-kit/addon/lib/d-menu-instance.js b/app/assets/javascripts/float-kit/addon/lib/d-menu-instance.js
index c3fc9b65067..33653217177 100644
--- a/app/assets/javascripts/float-kit/addon/lib/d-menu-instance.js
+++ b/app/assets/javascripts/float-kit/addon/lib/d-menu-instance.js
@@ -54,7 +54,7 @@ export default class DMenuInstance extends FloatKitInstance {
}
@action
- async close() {
+ async close(options = { focusTrigger: true }) {
if (getOwner(this).isDestroying) {
return;
}
@@ -66,6 +66,10 @@ export default class DMenuInstance extends FloatKitInstance {
}
await this.menu.close(this);
+
+ if (options.focusTrigger) {
+ this.trigger?.focus?.();
+ }
}
@action