Skip to content

Commit 67c4d69

Browse files
authored
feat(ui5-panel): implement headerAriaLabelledBy property (#2200)
1 parent 960f927 commit 67c4d69

16 files changed

+124
-40
lines changed
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import findNodeOwner from "./findNodeOwner.js";
2+
3+
const getEffectiveAriaLabelText = el => {
4+
if (!el.ariaLabelledby) {
5+
if (el.ariaLabel) {
6+
return el.ariaLabel;
7+
}
8+
9+
return undefined;
10+
}
11+
12+
return getAriaLabelledByTexts(el);
13+
};
14+
15+
/**
16+
*
17+
* @param {HTMLElement} el Defines the HTMLElement, for which you need to get all related texts
18+
* @param {HTMLElement} ownerDocument (Optional) Defines the HTMLElement(might document or custom element) where the you want to search for the texts.
19+
* @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
20+
*/
21+
const getAriaLabelledByTexts = (el, ownerDocument, readyIds = "") => {
22+
const ids = (readyIds && readyIds.split(" ")) || el.ariaLabelledby.split(" ");
23+
const owner = ownerDocument || findNodeOwner(el);
24+
let result = "";
25+
26+
ids.forEach((elementId, index) => {
27+
const element = owner.querySelector(`[id='${elementId}']`);
28+
result += `${element ? element.textContent : ""}`;
29+
30+
if (index < ids.length - 1) {
31+
result += " ";
32+
}
33+
});
34+
35+
return result;
36+
};
37+
38+
export {
39+
getEffectiveAriaLabelText,
40+
getAriaLabelledByTexts,
41+
};

packages/base/src/util/getEffectiveAriaLabelText.js

-28
This file was deleted.

packages/main/src/Button.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
33
import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js";
44
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
55
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
6-
import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js";
6+
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
77
import ButtonDesign from "./types/ButtonDesign.js";
88
import ButtonTemplate from "./generated/templates/ButtonTemplate.lit.js";
99
import Icon from "./Icon.js";

packages/main/src/Card.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
class="{{classes.main}}"
33
dir="{{effectiveDir}}"
44
role="region"
5-
aria-label="{{ariaLebelText}}"
5+
aria-label="{{ariaLabelText}}"
66
aria-labelledby="{{_id}}-desc {{_id}}-heading">
77
{{#if hasHeader}}
88
<div class="{{classes.header}}"

packages/main/src/Card.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
22
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
33
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
4-
import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js";
4+
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
55
import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js";
66
import CardTemplate from "./generated/templates/CardTemplate.lit.js";
77
import Icon from "./Icon.js";
@@ -238,7 +238,7 @@ class Card extends UI5Element {
238238
return !!(this.heading || this.subheading || this.status || this.hasAction || this.avatar);
239239
}
240240

241-
get ariaLebelText() {
241+
get ariaLabelText() {
242242
return getEffectiveAriaLabelText(this);
243243
}
244244

packages/main/src/ComboBox.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
33
import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js";
44
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";
55
import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
6-
import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js";
6+
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
77
import "@ui5/webcomponents-icons/dist/icons/slim-arrow-down.js";
88
import "@ui5/webcomponents-icons/dist/icons/decline.js";
99
import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";

packages/main/src/DatePicker.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import DateFormat from "@ui5/webcomponents-localization/dist/DateFormat.js";
99
import CalendarType from "@ui5/webcomponents-base/dist/types/CalendarType.js";
1010
import CalendarDate from "@ui5/webcomponents-localization/dist/dates/CalendarDate.js";
1111
import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js";
12-
import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js";
12+
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
1313
import { isShow, isF4 } from "@ui5/webcomponents-base/dist/Keys.js";
1414
import { isPhone, isIE } from "@ui5/webcomponents-base/dist/Device.js";
1515
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";

packages/main/src/Input.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from "@ui5/webcomponents-base/dist/Keys.js";
1515
import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
1616
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
17-
import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js";
17+
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
1818
import "@ui5/webcomponents-icons/dist/icons/decline.js";
1919
import InputType from "./types/InputType.js";
2020
import Popover from "./Popover.js";

packages/main/src/List.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation
44
import { getLastTabbableElement } from "@ui5/webcomponents-base/dist/util/TabbableElements.js";
55
import { isTabNext } from "@ui5/webcomponents-base/dist/Keys.js";
66
import NavigationMode from "@ui5/webcomponents-base/dist/types/NavigationMode.js";
7-
import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js";
7+
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
88
import ListMode from "./types/ListMode.js";
99
import ListSeparators from "./types/ListSeparators.js";
1010
import BusyIndicator from "./BusyIndicator.js";

packages/main/src/Panel.hbs

+4
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,16 @@
3939
role="heading"
4040
aria-level="{{headerAriaLevel}}"
4141
class="ui5-panel-header-title"
42+
aria-labelledby="{{_id}}-headerText"
4243
>
4344
{{headerText}}
4445
</div>
4546
{{/if}}
4647
</div>
4748

49+
<div id="aria-labelledby-texts"></div>
50+
<span id="{{_id}}-headerText" class="ui5-hidden-text">{{headerAriaLabelledByText}}</span>
51+
4852
<!-- content area -->
4953
<div class="ui5-panel-content" id="{{_id}}-content" tabindex="-1" style="{{styles.content}}">
5054
<slot></slot>

packages/main/src/Panel.js

+35-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import slideDown from "@ui5/webcomponents-base/dist/animations/slideDown.js";
44
import slideUp from "@ui5/webcomponents-base/dist/animations/slideUp.js";
55
import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js";
66
import AnimationMode from "@ui5/webcomponents-base/dist/types/AnimationMode.js";
7-
import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js";
7+
import {
8+
getEffectiveAriaLabelText,
9+
getAriaLabelledByTexts,
10+
} from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
811
import { getAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js";
912
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
1013
import "@ui5/webcomponents-icons/dist/icons/slim-arrow-right.js";
14+
import findNodeOwner from "@ui5/webcomponents-base/dist/util/findNodeOwner.js";
1115
import Button from "./Button.js";
1216
import TitleLevel from "./types/TitleLevel.js";
1317
import PanelAccessibleRole from "./types/PanelAccessibleRole.js";
@@ -118,6 +122,7 @@ const metadata = {
118122
type: TitleLevel,
119123
defaultValue: TitleLevel.H2,
120124
},
125+
121126
/**
122127
* @type {String}
123128
* @defaultvalue ""
@@ -127,6 +132,7 @@ const metadata = {
127132
ariaLabel: {
128133
type: String,
129134
},
135+
130136
/**
131137
* Receives id(or many ids) of the elements that label the panel
132138
*
@@ -139,23 +145,40 @@ const metadata = {
139145
type: String,
140146
defaultValue: "",
141147
},
148+
149+
/**
150+
* Receives id(or many ids) of the elements that label the header of the panel
151+
*
152+
* @type {String}
153+
* @defaultvalue ""
154+
* @private
155+
* @since 1.0.0-rc.9
156+
*/
157+
headerAriaLabelledby: {
158+
type: String,
159+
},
160+
142161
/**
143162
* @private
144163
*/
145164
_hasHeader: {
146165
type: Boolean,
147166
},
167+
148168
_header: {
149169
type: Object,
150170
},
171+
151172
_contentExpanded: {
152173
type: Boolean,
153174
noAttribute: true,
154175
},
176+
155177
_animationRunning: {
156178
type: Boolean,
157179
noAttribute: true,
158180
},
181+
159182
_buttonAccInfo: {
160183
type: Object,
161184
},
@@ -396,6 +419,10 @@ class Panel extends UI5Element {
396419
return getEffectiveAriaLabelText(this);
397420
}
398421

422+
get header() {
423+
return this.getDomRef().querySelector(`#${this._id}-header-title`);
424+
}
425+
399426
get headerAriaLevel() {
400427
return this.headerLevel.slice(1);
401428
}
@@ -404,6 +431,13 @@ class Panel extends UI5Element {
404431
return (this.header.length || this.fixed) ? "-1" : "0";
405432
}
406433

434+
get headerAriaLabelledByText() {
435+
if (!this.headerAriaLabelledby) {
436+
return;
437+
}
438+
return getAriaLabelledByTexts(this.header, findNodeOwner(this), this.headerAriaLabelledby);
439+
}
440+
407441
get nonFixedInternalHeader() {
408442
return !this._hasHeader && !this.fixed;
409443
}

packages/main/src/Select.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from "@ui5/webcomponents-base/dist/Keys.js";
1313
import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
1414
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
15-
import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js";
15+
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
1616
import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js";
1717
import "@ui5/webcomponents-icons/dist/icons/slim-arrow-down.js";
1818
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";

packages/main/src/TextArea.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
22
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
33
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
44
import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
5-
import getEffectiveAriaLabelText from "@ui5/webcomponents-base/dist/util/getEffectiveAriaLabelText.js";
5+
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
66
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
77
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
88
import { isIE } from "@ui5/webcomponents-base/dist/Device.js";

packages/main/src/themes/Panel.css

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@import "./InvisibleTextStyles.css";
2+
13
:host(:not([hidden])) {
24
display: block;
35
}

packages/main/test/pages/Panel.html

+32
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,38 @@
184184
<ui5-input id="field1" value="0"></ui5-input>
185185
<ui5-input id="field2" value="0"></ui5-input>
186186

187+
<section>
188+
<ui5-label id="info-state">Success</ui5-label>
189+
<ui5-label id="info">Helpfull message here</ui5-label>
190+
<ui5-panel id="panel-expandable" accessible-role="Complementary" header-text="Custom Aria labelledby texts" header-level="H4" header-aria-labelledby="info-state info">
191+
192+
193+
<!-- Content -->
194+
<ui5-title>Lorem ipsum!</ui5-title>
195+
<ui5-label wrap>
196+
<span>
197+
Lorem ipsum dolor sit amet, tamquam invidunt cu sed, unum regione mel ea, quo ea alia novum. Ne qui illud zril
198+
nostrum, vel ea sint dicant postea. Vel ne facete tritani, neglegentur concludaturque sed te. His animal dolorum ut.
199+
Aeterno appareat ei mei, cu sed elit scripserit, an quodsi oportere accusamus quo. Pri ea probo corpora rationibus,
200+
soluta incorrupte ex his.
201+
Mei ei brute cetero, id duo magna aeque torquatos. Quodsi erroribus mediocritatem his ut, ad pri legere iracundia
202+
democritum. Menandri intellegam in mea, ex vero movet qualisque sed. Maiorum verterem perfecto nec ea, est velit
203+
elaboraret consequuntur eu, eam ad reque postea admodum. Ne inimicus convenire pri, doctus vidisse te ius.
204+
Percipitur contentiones in vis, cu vim propriae phaedrum. Has ad magna errem honestatis, duo vero graeco epicurei
205+
no, populo semper sit ne. Vulputate dissentiunt interpretaris ea vis, nec civibus moderatius at. Cu vim stet
206+
dissentias, no vidit saperet indoctum nec, et pro magna prima nobis. Vis consul feugiat qualisque in, regione
207+
persecuti cotidieque id eos, id ius omnesque vituperata.
208+
Pri ex impedit percipit consulatu. Ius iudico feugiat instructior an. Iusto putant eum eu, ubique splendide pri ad,
209+
cu qui salutandi assentior percipitur. At esse ceteros salutandi ius. Te dicam reprehendunt nec, ea discere ponderum
210+
sensibus duo.
211+
Vis cu commodo definiebas, postea dissentias ne vim. Modo homero eos ad. Ut vix equidem temporibus. At duo audire
212+
volumus, id volumus rationibus vim. Sit ne diam volumus. Augue labitur mel cu, an eam omnis causae hendrerit.
213+
</span>
214+
</ui5-label>
215+
216+
</ui5-panel>
217+
</section>
218+
187219
</body>
188220

189221
</html>

packages/main/test/specs/Card.spec.js

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ describe("Card general interaction", () => {
3333
assert.strictEqual(field.getProperty("value"), "3", "The events count should remain 3 as the header is not interactive.");
3434
});
3535

36-
3736
it("Tests aria-label and aria-labelledby", () => {
3837
const card1 = browser.$("#textAreaAriaLabel").shadow$(".ui5-card-root");
3938
const card2 = browser.$("#textAreaAriaLabelledBy").shadow$(".ui5-card-root");

0 commit comments

Comments
 (0)