diff --git a/packages/main/src/Dialog.ts b/packages/main/src/Dialog.ts index 89bd2b46ca4b..4bab16b50408 100644 --- a/packages/main/src/Dialog.ts +++ b/packages/main/src/Dialog.ts @@ -198,6 +198,10 @@ class Dialog extends Popup { _cachedMinHeight?: number; _draggedOrResized = false; _dragHandlerRegistered = false; + _liveTextTimeout?: ReturnType; + + @property({ noAttribute: true }) + _liveText = ""; /** * Defines the header HTML Element. @@ -327,9 +331,33 @@ class Dialog extends Popup { return toLowercaseEnumValue(this.accessibleRole); } + get _contentDescriptionText(): string { + return this.content + .map(el => { + return (el instanceof HTMLElement) ? el.textContent?.trim() : ""; + }) + .filter(Boolean) + .join(" "); + } + _show() { super._show(); this._center(); + + // VoiceOver on macOS does not announce text from the dialog content, + // so aria-live region is used to announce text-only content when the dialog opens. + const text = this._contentDescriptionText; + if (text) { + this._liveTextTimeout = setTimeout(() => { + this._liveText = text; + }, 100); + } + } + + closePopup(escPressed = false, preventRegistryUpdate = false, preventFocusRestore = false): void { + clearTimeout(this._liveTextTimeout); + this._liveText = ""; + super.closePopup(escPressed, preventRegistryUpdate, preventFocusRestore); } onBeforeRendering() { diff --git a/packages/main/src/DialogTemplate.tsx b/packages/main/src/DialogTemplate.tsx index 31bdd6f54300..9811048e3857 100644 --- a/packages/main/src/DialogTemplate.tsx +++ b/packages/main/src/DialogTemplate.tsx @@ -53,6 +53,7 @@ function beforeContent(this: Dialog) { function afterContent(this: Dialog) { return (<> + {this._liveText} {!!this.footer.length &&