diff --git a/packages/main/cypress/specs/Dialog.cy.tsx b/packages/main/cypress/specs/Dialog.cy.tsx index 686ad9cef953..a9ded9140d87 100644 --- a/packages/main/cypress/specs/Dialog.cy.tsx +++ b/packages/main/cypress/specs/Dialog.cy.tsx @@ -1244,6 +1244,59 @@ describe("Acc", () => { .and("have.attr", "aria-modal", "true"); }); + it("tests header, content and footer regions", () => { + cy.mount( + +
Some content
+ +
+ ); + + cy.get("#dialog-regions") + .invoke("prop", "open", true); + + cy.get("#dialog-regions").ui5DialogOpened(); + + // Header region + cy.get("#dialog-regions") + .shadow() + .find(".ui5-popup-header-root") + .should("have.attr", "role", "region") + .and("have.attr", "aria-label", "Header"); + + // Content region + cy.get("#dialog-regions") + .shadow() + .find(".ui5-popup-content") + .should("have.attr", "role", "region") + .and("have.attr", "aria-label", "Content"); + + // Footer region + cy.get("#dialog-regions") + .shadow() + .find(".ui5-popup-footer-root") + .should("have.attr", "role", "region") + .and("have.attr", "aria-label", "Footer"); + }); + + it("tests footer region is not rendered when no footer slot is provided", () => { + cy.mount( + +
Some content
+
+ ); + + cy.get("#dialog-no-footer") + .invoke("prop", "open", true); + + cy.get("#dialog-no-footer").ui5DialogOpened(); + + cy.get("#dialog-no-footer") + .shadow() + .find(".ui5-popup-footer-root") + .should("not.exist"); + }); + }); describe("Page scrolling", () => { diff --git a/packages/main/src/Dialog.ts b/packages/main/src/Dialog.ts index 89bd2b46ca4b..9596e0562044 100644 --- a/packages/main/src/Dialog.ts +++ b/packages/main/src/Dialog.ts @@ -22,6 +22,9 @@ import { DIALOG_HEADER_ARIA_DESCRIBEDBY_RESIZABLE, DIALOG_HEADER_ARIA_DESCRIBEDBY_DRAGGABLE, DIALOG_HEADER_ARIA_DESCRIBEDBY_DRAGGABLE_RESIZABLE, + DIALOG_HEADER_ARIA_LABEL, + DIALOG_CONTENT_ARIA_LABEL, + DIALOG_FOOTER_ARIA_LABEL, } from "./generated/i18n/i18n-defaults.js"; // Template @@ -327,6 +330,22 @@ class Dialog extends Popup { return toLowercaseEnumValue(this.accessibleRole); } + get _contentRole(): "region" { + return "region"; + } + + get _headerAriaLabel() { + return Dialog.i18nBundle.getText(DIALOG_HEADER_ARIA_LABEL); + } + + get _contentAriaLabel() { + return Dialog.i18nBundle.getText(DIALOG_CONTENT_ARIA_LABEL); + } + + get _footerAriaLabel() { + return Dialog.i18nBundle.getText(DIALOG_FOOTER_ARIA_LABEL); + } + _show() { super._show(); this._center(); diff --git a/packages/main/src/DialogTemplate.tsx b/packages/main/src/DialogTemplate.tsx index 31bdd6f54300..3575a770d021 100644 --- a/packages/main/src/DialogTemplate.tsx +++ b/packages/main/src/DialogTemplate.tsx @@ -14,39 +14,38 @@ export default function DialogTemplate(this: Dialog) { function beforeContent(this: Dialog) { return (<> {!!this._displayHeader && -
-
- {this.hasValueState && - - } - {this.header.length ? - - : - {this.headerText} - } +
+ {this.hasValueState && + + } + {this.header.length ? + + : + {this.headerText} + } - {this.resizable ? - this.draggable ? - - : - + {this.resizable ? + this.draggable ? + : - this.draggable && - - } -
-
+ + : + this.draggable && + + } + } ); } @@ -54,9 +53,14 @@ function beforeContent(this: Dialog) { function afterContent(this: Dialog) { return (<> {!!this.footer.length && -
+
+ } {this._showResizeHandle &&
+
diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index b43e02c4c878..6e44a54d20c8 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -840,6 +840,15 @@ DIALOG_HEADER_ARIA_DESCRIBEDBY_DRAGGABLE=Use Arrow keys to move #XACT: ARIA announcement for describedby attribute of draggable and resizable Dialog header DIALOG_HEADER_ARIA_DESCRIBEDBY_DRAGGABLE_RESIZABLE=Use Arrow keys to move, Shift+Arrow keys to resize + +#XACT: ARIA label for the Dialog header region +DIALOG_HEADER_ARIA_LABEL=Header + +#XACT: ARIA label for the Dialog content region +DIALOG_CONTENT_ARIA_LABEL=Content + +#XACT: ARIA label for the Dialog footer region +DIALOG_FOOTER_ARIA_LABEL=Footer #XFLD: A colon to separate the "label" from an input. In some languages there might be a different symbol used for such a colon LABEL_COLON=: