diff --git a/packages/base/src/util/AriaLabelHelper.js b/packages/base/src/util/AriaLabelHelper.js new file mode 100644 index 000000000000..e5dc45a2c1a0 --- /dev/null +++ b/packages/base/src/util/AriaLabelHelper.js @@ -0,0 +1,41 @@ +import findNodeOwner from "./findNodeOwner.js"; + +const getEffectiveAriaLabelText = el => { + if (!el.ariaLabelledby) { + if (el.ariaLabel) { + return el.ariaLabel; + } + + return undefined; + } + + return getAriaLabelledByTexts(el); +}; + +/** + * + * @param {HTMLElement} el Defines the HTMLElement, for which you need to get all related texts + * @param {HTMLElement} ownerDocument (Optional) Defines the HTMLElement(might document or custom element) where the you want to search for the texts. + * @param {String} readyIds (Optional) Defines a string of elements ids. The text of these elements will be returned. If used you should provide either el or ownerDocument + */ +const getAriaLabelledByTexts = (el, ownerDocument, readyIds = "") => { + const ids = (readyIds && readyIds.split(" ")) || el.ariaLabelledby.split(" "); + const owner = ownerDocument || findNodeOwner(el); + let result = ""; + + ids.forEach((elementId, index) => { + const element = owner.querySelector(`[id='${elementId}']`); + result += `${element ? element.textContent : ""}`; + + if (index < ids.length - 1) { + result += " "; + } + }); + + return result; +}; + +export { + getEffectiveAriaLabelText, + getAriaLabelledByTexts, +}; diff --git a/packages/base/src/util/getEffectiveAriaLabelText.js b/packages/base/src/util/getEffectiveAriaLabelText.js deleted file mode 100644 index ea32e7ae5647..000000000000 --- a/packages/base/src/util/getEffectiveAriaLabelText.js +++ /dev/null @@ -1,28 +0,0 @@ -import findNodeOwner from "./findNodeOwner.js"; - -const getEffectiveAriaLabelText = el => { - if (!el.ariaLabelledby) { - if (el.ariaLabel) { - return el.ariaLabel; - } - - return undefined; - } - - const ids = el.ariaLabelledby.split(" "); - const owner = findNodeOwner(el); - let result = ""; - - ids.forEach((elementId, index) => { - const element = owner.querySelector(`[id='${elementId}']`); - result += `${element ? element.textContent : ""}`; - - if (index < ids.length - 1) { - result += " "; - } - }); - - return result; -}; - -export default getEffectiveAriaLabelText; diff --git a/packages/main/src/Button.js b/packages/main/src/Button.js index cca223285988..403d72a53385 100644 --- a/packages/main/src/Button.js +++ b/packages/main/src/Button.js @@ -3,7 +3,7 @@ import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js"; import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js"; import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; -import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js"; +import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js"; import ButtonDesign from "./types/ButtonDesign.js"; import ButtonTemplate from "./generated/templates/ButtonTemplate.lit.js"; import Icon from "./Icon.js"; diff --git a/packages/main/src/Card.hbs b/packages/main/src/Card.hbs index ec6350518e77..d2970289be24 100644 --- a/packages/main/src/Card.hbs +++ b/packages/main/src/Card.hbs @@ -2,7 +2,7 @@ class="{{classes.main}}" dir="{{effectiveDir}}" role="region" - aria-label="{{ariaLebelText}}" + aria-label="{{ariaLabelText}}" aria-labelledby="{{_id}}-desc {{_id}}-heading"> {{#if hasHeader}}
{{headerText}}
{{/if}} +
+ {{headerAriaLabelledByText}} +
diff --git a/packages/main/src/Panel.js b/packages/main/src/Panel.js index d811c54c87ec..3f887672f6ce 100644 --- a/packages/main/src/Panel.js +++ b/packages/main/src/Panel.js @@ -4,10 +4,14 @@ import slideDown from "@ui5/webcomponents-base/dist/animations/slideDown.js"; import slideUp from "@ui5/webcomponents-base/dist/animations/slideUp.js"; import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js"; import AnimationMode from "@ui5/webcomponents-base/dist/types/AnimationMode.js"; -import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js"; +import { + getEffectiveAriaLabelText, + getAriaLabelledByTexts, +} from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js"; import { getAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js"; import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import "@ui5/webcomponents-icons/dist/icons/slim-arrow-right.js"; +import findNodeOwner from "@ui5/webcomponents-base/dist/util/findNodeOwner.js"; import Button from "./Button.js"; import TitleLevel from "./types/TitleLevel.js"; import PanelAccessibleRole from "./types/PanelAccessibleRole.js"; @@ -118,6 +122,7 @@ const metadata = { type: TitleLevel, defaultValue: TitleLevel.H2, }, + /** * @type {String} * @defaultvalue "" @@ -127,6 +132,7 @@ const metadata = { ariaLabel: { type: String, }, + /** * Receives id(or many ids) of the elements that label the panel * @@ -139,23 +145,40 @@ const metadata = { type: String, defaultValue: "", }, + + /** + * Receives id(or many ids) of the elements that label the header of the panel + * + * @type {String} + * @defaultvalue "" + * @private + * @since 1.0.0-rc.9 + */ + headerAriaLabelledby: { + type: String, + }, + /** * @private */ _hasHeader: { type: Boolean, }, + _header: { type: Object, }, + _contentExpanded: { type: Boolean, noAttribute: true, }, + _animationRunning: { type: Boolean, noAttribute: true, }, + _buttonAccInfo: { type: Object, }, @@ -396,6 +419,10 @@ class Panel extends UI5Element { return getEffectiveAriaLabelText(this); } + get header() { + return this.getDomRef().querySelector(`#${this._id}-header-title`); + } + get headerAriaLevel() { return this.headerLevel.slice(1); } @@ -404,6 +431,13 @@ class Panel extends UI5Element { return (this.header.length || this.fixed) ? "-1" : "0"; } + get headerAriaLabelledByText() { + if (!this.headerAriaLabelledby) { + return; + } + return getAriaLabelledByTexts(this.header, findNodeOwner(this), this.headerAriaLabelledby); + } + get nonFixedInternalHeader() { return !this._hasHeader && !this.fixed; } diff --git a/packages/main/src/Select.js b/packages/main/src/Select.js index f383f138f1a7..700714a22d6b 100644 --- a/packages/main/src/Select.js +++ b/packages/main/src/Select.js @@ -12,7 +12,7 @@ import { } from "@ui5/webcomponents-base/dist/Keys.js"; import Integer from "@ui5/webcomponents-base/dist/types/Integer.js"; import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js"; -import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js"; +import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js"; import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; import "@ui5/webcomponents-icons/dist/icons/slim-arrow-down.js"; import { isPhone } from "@ui5/webcomponents-base/dist/Device.js"; diff --git a/packages/main/src/TextArea.js b/packages/main/src/TextArea.js index eb3fbd0a3c71..5dd44ec63708 100644 --- a/packages/main/src/TextArea.js +++ b/packages/main/src/TextArea.js @@ -2,7 +2,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; import Integer from "@ui5/webcomponents-base/dist/types/Integer.js"; -import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js"; +import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js"; import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js"; import { isIE } from "@ui5/webcomponents-base/dist/Device.js"; diff --git a/packages/main/src/themes/Panel.css b/packages/main/src/themes/Panel.css index e65d145b488c..62d2bea65186 100644 --- a/packages/main/src/themes/Panel.css +++ b/packages/main/src/themes/Panel.css @@ -1,3 +1,5 @@ +@import "./InvisibleTextStyles.css"; + :host(:not([hidden])) { display: block; } diff --git a/packages/main/test/pages/Panel.html b/packages/main/test/pages/Panel.html index 66db69f7f9cb..924a42de07fd 100644 --- a/packages/main/test/pages/Panel.html +++ b/packages/main/test/pages/Panel.html @@ -184,6 +184,38 @@ +
+ Success + Helpfull message here + + + + + Lorem ipsum! + + + Lorem ipsum dolor sit amet, tamquam invidunt cu sed, unum regione mel ea, quo ea alia novum. Ne qui illud zril + nostrum, vel ea sint dicant postea. Vel ne facete tritani, neglegentur concludaturque sed te. His animal dolorum ut. + Aeterno appareat ei mei, cu sed elit scripserit, an quodsi oportere accusamus quo. Pri ea probo corpora rationibus, + soluta incorrupte ex his. + Mei ei brute cetero, id duo magna aeque torquatos. Quodsi erroribus mediocritatem his ut, ad pri legere iracundia + democritum. Menandri intellegam in mea, ex vero movet qualisque sed. Maiorum verterem perfecto nec ea, est velit + elaboraret consequuntur eu, eam ad reque postea admodum. Ne inimicus convenire pri, doctus vidisse te ius. + Percipitur contentiones in vis, cu vim propriae phaedrum. Has ad magna errem honestatis, duo vero graeco epicurei + no, populo semper sit ne. Vulputate dissentiunt interpretaris ea vis, nec civibus moderatius at. Cu vim stet + dissentias, no vidit saperet indoctum nec, et pro magna prima nobis. Vis consul feugiat qualisque in, regione + persecuti cotidieque id eos, id ius omnesque vituperata. + Pri ex impedit percipit consulatu. Ius iudico feugiat instructior an. Iusto putant eum eu, ubique splendide pri ad, + cu qui salutandi assentior percipitur. At esse ceteros salutandi ius. Te dicam reprehendunt nec, ea discere ponderum + sensibus duo. + Vis cu commodo definiebas, postea dissentias ne vim. Modo homero eos ad. Ut vix equidem temporibus. At duo audire + volumus, id volumus rationibus vim. Sit ne diam volumus. Augue labitur mel cu, an eam omnis causae hendrerit. + + + + +
+ diff --git a/packages/main/test/specs/Card.spec.js b/packages/main/test/specs/Card.spec.js index 4fd27ae851e7..d70306a558b5 100644 --- a/packages/main/test/specs/Card.spec.js +++ b/packages/main/test/specs/Card.spec.js @@ -33,7 +33,6 @@ describe("Card general interaction", () => { assert.strictEqual(field.getProperty("value"), "3", "The events count should remain 3 as the header is not interactive."); }); - it("Tests aria-label and aria-labelledby", () => { const card1 = browser.$("#textAreaAriaLabel").shadow$(".ui5-card-root"); const card2 = browser.$("#textAreaAriaLabelledBy").shadow$(".ui5-card-root");