UX: Wait for render before invoking A11YDialog (#24100)

Previously, focus wasn't being applied correctly on dialogs using named
components. This was because the A11YDialog was being invoked before
the component was completely rendered.

The long-term plan is to move away from A11YDialog doing the rendering
here, but for now this should do.
This commit is contained in:
Penar Musaraj 2023-10-26 08:24:47 -04:00 committed by GitHub
parent d405305456
commit b8ee52c4cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 18 additions and 21 deletions

View File

@ -16,7 +16,7 @@ export default class AdminWebHooksIndexController extends Controller {
@alias("adminWebHooks.model") model; @alias("adminWebHooks.model") model;
@action @action
destroy(webhook) { destroyWebhook(webhook) {
return this.dialog.deleteConfirm({ return this.dialog.deleteConfirm({
message: I18n.t("admin.web_hooks.delete_confirm"), message: I18n.t("admin.web_hooks.delete_confirm"),
didConfirm: async () => { didConfirm: async () => {

View File

@ -15,7 +15,7 @@ export default class AdminWebHooksShowController extends Controller {
} }
@action @action
destroy() { destroyWebhook() {
return this.dialog.deleteConfirm({ return this.dialog.deleteConfirm({
message: I18n.t("admin.web_hooks.delete_confirm"), message: I18n.t("admin.web_hooks.delete_confirm"),
didConfirm: async () => { didConfirm: async () => {

View File

@ -51,7 +51,7 @@
</LinkTo> </LinkTo>
<DButton <DButton
@action={{fn this.destroy webhook}} @action={{fn this.destroyWebhook webhook}}
@icon="times" @icon="times"
@title="delete" @title="delete"
class="destroy btn-danger" class="destroy btn-danger"

View File

@ -15,7 +15,7 @@
/> />
<DButton <DButton
@action={{this.destroy}} @action={{this.destroyWebhook}}
@icon="times" @icon="times"
@title="delete" @title="delete"
class="destroy btn-danger admin-webhooks__delete-button" class="destroy btn-danger admin-webhooks__delete-button"

View File

@ -1,4 +1,4 @@
import { next } from "@ember/runloop"; import { schedule } from "@ember/runloop";
import Service from "@ember/service"; import Service from "@ember/service";
import A11yDialog from "a11y-dialog"; import A11yDialog from "a11y-dialog";
import { bind } from "discourse-common/utils/decorators"; import { bind } from "discourse-common/utils/decorators";
@ -49,26 +49,11 @@ export default class DialogService extends Service {
buttons, buttons,
} = params; } = params;
let element = document.getElementById("dialog-holder");
if (!element) {
await new Promise((resolve) => next(resolve));
element = document.getElementById("dialog-holder");
}
if (!element) {
const msg =
"dialog-holder wrapper element not found. Unable to render dialog";
// eslint-disable-next-line no-console
console.error(msg, params);
throw new Error(msg);
}
this.setProperties({ this.setProperties({
message, message,
bodyComponent, bodyComponent,
bodyComponentModel, bodyComponentModel,
type, type,
dialogInstance: new A11yDialog(element),
title, title,
titleElementId: title !== null ? "dialog-title" : null, titleElementId: title !== null ? "dialog-title" : null,
@ -88,6 +73,18 @@ export default class DialogService extends Service {
class: params.class, class: params.class,
}); });
await new Promise((resolve) => schedule("afterRender", resolve));
const element = document.getElementById("dialog-holder");
if (!element) {
const msg =
"dialog-holder wrapper element not found. Unable to render dialog";
// eslint-disable-next-line no-console
console.error(msg, params);
throw new Error(msg);
}
this.dialogInstance = new A11yDialog(element);
this.dialogInstance.show(); this.dialogInstance.show();
this.dialogInstance.on("hide", () => { this.dialogInstance.on("hide", () => {

View File

@ -33,7 +33,7 @@ acceptance("Admin - Plugins", function (needs) {
); );
server.put("/admin/site_settings/testplugin_enabled", () => server.put("/admin/site_settings/testplugin_enabled", () =>
helper.response() helper.response(200, {})
); );
}); });