Skip to content

Commit 43ac177

Browse files
dobrinyonkovilhan007
authored andcommitted
feat(ui5-avatar-group): initial implementation (#2524)
Introduce new component in the main package, called AvatarGroup. The component is used to display a group of avatars arranged horizontally. It is useful to visually showcase a group of related avatars, such as, project team members or employees. The control allows you to display the avatars in different sizes, depending on your use case. Supports 2 main types - Group and Individual: - Group type: The avatars are displayed as partially overlapped on top of each other and the entire group has one click/tap area. - Individual type: The avatars are displayed side-by-side and each avatar has its own click/tap area. Fixes: #2409
1 parent a09a068 commit 43ac177

File tree

20 files changed

+1508
-11
lines changed

20 files changed

+1508
-11
lines changed

packages/main/bundle.esm.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import "./dist/features/InputElementsFormSupport.js";
4141
import "./dist/features/InputSuggestions.js";
4242

4343
import Avatar from "./dist/Avatar.js";
44+
import AvatarGroup from "./dist/AvatarGroup.js";
4445
import Badge from "./dist/Badge.js";
4546
import BusyIndicator from "./dist/BusyIndicator.js";
4647
import Button from "./dist/Button.js";

packages/main/src/Avatar.hbs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
<div class="ui5-avatar-root">
1+
<div
2+
class="ui5-avatar-root"
3+
tabindex="{{tabindex}}"
4+
data-sap-focus-ref
5+
@keyup={{_onkeyup}}
6+
@keydown={{_onkeydown}}
7+
@focusout={{_onfocusout}}
8+
@focusin={{_onfocusin}}
9+
@click={{_onclick}}
10+
>
211
{{#if image}}
312
<span class="ui5-avatar-img" style="{{styles.img}}" role="img" aria-label="{{accessibleNameText}}"></span>
413
{{else if icon}}

packages/main/src/Avatar.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
33
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
44
import encodeCSS from "@ui5/webcomponents-base/dist/util/encodeCSS.js";
55

6+
import { isEnter, isSpace } from "@ui5/webcomponents-base/dist/Keys.js";
67
// Template
78
import AvatarTemplate from "./generated/templates/AvatarTemplate.lit.js";
89

@@ -25,6 +26,24 @@ const metadata = {
2526
languageAware: true,
2627
properties: /** @lends sap.ui.webcomponents.main.Avatar.prototype */ {
2728

29+
/**
30+
* Defines if the avatar is interactive (focusable and pressable)
31+
* @type {boolean}
32+
* @defaultValue false
33+
* @public
34+
*/
35+
interactive: {
36+
type: Boolean,
37+
},
38+
39+
/**
40+
* Indicates if the elements is on focus
41+
* @private
42+
*/
43+
focused: {
44+
type: Boolean,
45+
},
46+
2847
/**
2948
* Defines the source path to the desired image.
3049
* @type {string}
@@ -105,6 +124,14 @@ const metadata = {
105124
defaultValue: AvatarSize.S,
106125
},
107126

127+
/**
128+
* @private
129+
*/
130+
_size: {
131+
type: String,
132+
defaultValue: AvatarSize.S,
133+
},
134+
108135
/**
109136
* Defines the fit type of the desired image.
110137
* <br><br>
@@ -148,6 +175,14 @@ const metadata = {
148175
defaultValue: AvatarBackgroundColor.Accent6,
149176
},
150177

178+
/**
179+
* @private
180+
*/
181+
_backgroundColor: {
182+
type: String,
183+
defaultValue: AvatarBackgroundColor.Accent6,
184+
},
185+
151186
/**
152187
* Defines the text alternative of the <code>ui5-avatar</code>.
153188
* If not provided a default text alternative will be set, if present.
@@ -160,10 +195,23 @@ const metadata = {
160195
accessibleName: {
161196
type: String,
162197
},
198+
199+
_tabIndex: {
200+
type: String,
201+
noAttribute: true,
202+
},
163203
},
164204
slots: /** @lends sap.ui.webcomponents.main.Avatar.prototype */ {
165205
},
166206
events: /** @lends sap.ui.webcomponents.main.Avatar.prototype */ {
207+
/**
208+
* Fired on mouseup, space and enter if avatar is interactive
209+
*
210+
* @event
211+
* @private
212+
* @since 1.0.0-rc.11
213+
*/
214+
click: {},
167215
},
168216
};
169217

@@ -220,6 +268,34 @@ class Avatar extends UI5Element {
220268
await fetchI18nBundle("@ui5/webcomponents");
221269
}
222270

271+
get tabindex() {
272+
return this._tabIndex || (this.interactive ? "0" : "-1");
273+
}
274+
275+
/**
276+
* Returns the effective avatar size.
277+
* @readonly
278+
* @type { String }
279+
* @defaultValue "S"
280+
* @private
281+
*/
282+
get _effectiveSize() {
283+
// we read the attribute, because the "size" property will always have a default value
284+
return this.getAttribute("size") || this._size;
285+
}
286+
287+
/**
288+
* Returns the effective background color.
289+
* @readonly
290+
* @type { String }
291+
* @defaultValue "Accent6"
292+
* @private
293+
*/
294+
get _effectiveBackgroundColor() {
295+
// we read the attribute, because the "background-color" property will always have a default value
296+
return this.getAttribute("background-color") || this._backgroundColor;
297+
}
298+
223299
get validInitials() {
224300
const validInitials = /^[a-zA-Z]{1,2}$/;
225301

@@ -245,6 +321,37 @@ class Avatar extends UI5Element {
245321
},
246322
};
247323
}
324+
325+
_onclick(event) {
326+
event.isMarked = "avatar";
327+
if (this.interactive) {
328+
event.preventDefault();
329+
// Prevent the native event and fire custom event because otherwise the noConfict event won't be thrown
330+
this.fireEvent("click");
331+
}
332+
}
333+
334+
_onkeydown(event) {
335+
if (this.interactive && isEnter(event)) {
336+
this.fireEvent("click");
337+
}
338+
}
339+
340+
_onkeyup(event) {
341+
if (this.interactive && !event.shiftKey && isSpace(event)) {
342+
this.fireEvent("click");
343+
}
344+
}
345+
346+
_onfocusout() {
347+
this.focused = false;
348+
}
349+
350+
_onfocusin() {
351+
if (this.interactive) {
352+
this.focused = true;
353+
}
354+
}
248355
}
249356

250357
Avatar.define();

packages/main/src/AvatarGroup.hbs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<div class="ui5-avatar-group-root">
2+
<div
3+
class="ui5-avatar-group-items"
4+
@keyup="{{_onkeyup}}"
5+
@keydown="{{_onkeydown}}"
6+
@focusin="{{_onfocusin}}"
7+
tabindex="{{_groupTabIndex}}"
8+
@click="{{_onGroupClick}}"
9+
@ui5-click="{{_onUI5Click}}"
10+
>
11+
<slot></slot>
12+
13+
<ui5-button ?hidden="{{_overflowBtnHidden}}" tabindex="{{_overflowButtonTabIndex}}" class="ui5-avatar-group-overflow-btn">
14+
{{_overflowButtonText}}
15+
</ui5-button>
16+
</div>
17+
</div>

0 commit comments

Comments
 (0)