@@ -2,11 +2,21 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
2
2
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js" ;
3
3
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js" ;
4
4
import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js" ;
5
+ import { fetchI18nBundle , getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js" ;
6
+
5
7
import {
6
8
isEnter ,
7
9
isSpace ,
8
10
} from "@ui5/webcomponents-base/dist/Keys.js" ;
9
11
12
+ import {
13
+ AVATAR_GROUP_DISPLAYED_HIDDEN_LABEL ,
14
+ AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL ,
15
+ AVATAR_GROUP_ARIA_LABEL_INDIVIDUAL ,
16
+ AVATAR_GROUP_ARIA_LABEL_GROUP ,
17
+ AVATAR_GROUP_MOVE ,
18
+ } from "./generated/i18n/i18n-defaults.js" ;
19
+
10
20
// Template
11
21
import AvatarGroupTemplate from "./generated/templates/AvatarGroupTemplate.lit.js" ;
12
22
// Styles
@@ -89,6 +99,22 @@ const metadata = {
89
99
defaultValue : AvatarSize . S ,
90
100
} ,
91
101
102
+ /**
103
+ * Defines the aria-haspopup value of the <code>ui5-avatar-group</code> on:
104
+ * <br><br>
105
+ * <ul>
106
+ * <li> the whole container when <code>type</code> property is <code>Group</code></li>
107
+ * <li> the default "More" overflow button when <code>type</code> is <code>Individual</code></li>
108
+ * </ul>
109
+ * <br><br>
110
+ * @type String
111
+ * @since 1.0.0-rc.15
112
+ * @protected
113
+ */
114
+ ariaHaspopup : {
115
+ type : String ,
116
+ } ,
117
+
92
118
/**
93
119
* @private
94
120
*/
@@ -196,6 +222,30 @@ const metadata = {
196
222
* <li>You want to use it for other visual content than avatars.</li>
197
223
* </ul>
198
224
*
225
+ * <h3>Keyboard Handling</h3>
226
+ * The <code>ui5-avatar-group</code> provides advanced keyboard handling.
227
+ * When focused, the user can use the following keyboard
228
+ * shortcuts in order to perform a navigation:
229
+ * <br>
230
+ * - <code>type</code> Individual:
231
+ * <br>
232
+ * <ul>
233
+ * <li>[TAB] - Move focus to the overflow button</li>
234
+ * <li>[LEFT] - Navigate one avatar to the left</li>
235
+ * <li>[RIGHT] - Navigate one avatar to the right</li>
236
+ * <li>[HOME] - Navigate to the first avatar</li>
237
+ * <li>[END] - Navigate to the last avatar</li>
238
+ * <li>[SPACE],[ENTER],[RETURN] - Trigger <code>ui5-click</code> event</li>
239
+ * </ul>
240
+ * <br>
241
+ * - <code>type</code> Group:
242
+ * <br>
243
+ * <ul>
244
+ * <li>[TAB] - Move focus to the next interactive element after the <code>ui5-avatar-group</code></li>
245
+ * <li>[SPACE],[ENTER],[RETURN] - Trigger <code>ui5-click</code> event</li>
246
+ * </ul>
247
+ * <br>
248
+ *
199
249
* @constructor
200
250
* @author SAP SE
201
251
* @alias sap.ui.webcomponents.main.AvatarGroup
@@ -217,6 +267,8 @@ class AvatarGroup extends UI5Element {
217
267
this . _colorIndex = 0 ;
218
268
this . _hiddenItems = 0 ;
219
269
this . _onResizeHandler = this . _onResize . bind ( this ) ;
270
+
271
+ this . i18nBundle = getI18nBundle ( "@ui5/webcomponents" ) ;
220
272
}
221
273
222
274
static get metadata ( ) {
@@ -241,6 +293,10 @@ class AvatarGroup extends UI5Element {
241
293
] ;
242
294
}
243
295
296
+ static async onDefine ( ) {
297
+ await fetchI18nBundle ( "@ui5/webcomponents" ) ;
298
+ }
299
+
244
300
/**
245
301
* Returns an array containing the <code>ui5-avatar</code> instances that are currently not displayed due to lack of space.
246
302
* @readonly
@@ -267,6 +323,45 @@ class AvatarGroup extends UI5Element {
267
323
return this . overflowButton . length ? this . overflowButton [ 0 ] : undefined ;
268
324
}
269
325
326
+ get _ariaLabelText ( ) {
327
+ const hiddenItemsCount = this . hiddenItems . length ;
328
+ const typeLabelKey = this . _isGroup ? AVATAR_GROUP_ARIA_LABEL_GROUP : AVATAR_GROUP_ARIA_LABEL_INDIVIDUAL ;
329
+
330
+ // avatar type label
331
+ let text = this . i18nBundle . getText ( typeLabelKey ) ;
332
+
333
+ // add displayed-hidden avatars label
334
+ text += ` ${ this . i18nBundle . getText ( AVATAR_GROUP_DISPLAYED_HIDDEN_LABEL , [ this . _itemsCount - hiddenItemsCount ] , [ hiddenItemsCount ] ) } ` ;
335
+
336
+ if ( this . _isGroup ) {
337
+ // the container role is "button", add the message for complete list activation
338
+ text += ` ${ this . i18nBundle . getText ( AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL ) } ` ;
339
+ } else {
340
+ // the container role is "group", add the "how to navigate" message
341
+ text += ` ${ this . i18nBundle . getText ( AVATAR_GROUP_MOVE ) } ` ;
342
+ }
343
+
344
+ return text ;
345
+ }
346
+
347
+ get _overflowButtonAriaLabelText ( ) {
348
+ return this . _isGroup ? undefined : this . i18nBundle . getText ( AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL ) ;
349
+ }
350
+
351
+ get _containerAriaHasPopup ( ) {
352
+ return this . _isGroup ? this . _getAriaHasPopup ( ) : undefined ;
353
+ }
354
+
355
+ get _overflowButtonAccInfo ( ) {
356
+ return {
357
+ ariaHaspopup : this . _isGroup ? undefined : this . _getAriaHasPopup ( ) ,
358
+ } ;
359
+ }
360
+
361
+ get _role ( ) {
362
+ return this . _isGroup ? "button" : "group" ;
363
+ }
364
+
270
365
get _hiddenStartIndex ( ) {
271
366
return this . _itemsCount - this . _hiddenItems ;
272
367
}
@@ -504,6 +599,14 @@ class AvatarGroup extends UI5Element {
504
599
this . fireEvent ( "overflow" ) ;
505
600
}
506
601
}
602
+
603
+ _getAriaHasPopup ( ) {
604
+ if ( this . ariaHaspopup === "" ) {
605
+ return ;
606
+ }
607
+
608
+ return this . ariaHaspopup ;
609
+ }
507
610
}
508
611
509
612
AvatarGroup . define ( ) ;
0 commit comments