Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESL Avatar #2101

Open
wants to merge 4 commits into
base: epic/avatar
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pages/src/localdev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
ESLTooltip,
ESLAnimate,
ESLAnimateMixin,
ESLAvatar,
ESLRelatedTarget
} from '@exadel/esl/modules/all';

Expand Down Expand Up @@ -116,6 +117,8 @@ ESLTooltip.register();
ESLAnimate.register();
ESLAnimateMixin.register();

ESLAvatar.register();

// Register ESL Mixins
ESLRelatedTarget.register();

Expand Down
Binary file added pages/static/assets/avatar/animation.webp
Binary file not shown.
Binary file added pages/static/assets/avatar/transparent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pages/static/assets/avatar/transparent.webp
Binary file not shown.
Binary file added pages/static/assets/avatar/user.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pages/static/assets/avatar/user.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pages/static/assets/avatar/user.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pages/static/assets/avatar/user.webp
Binary file not shown.
9 changes: 9 additions & 0 deletions pages/static/assets/examples/avatar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions pages/views/components/esl-avatar.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
layout: content
title: ESL Avatar
seoTitle: ESL Avatar is a custom element used to represent a user's profile picture
name: ESL Avatar
tags: [components, beta]
aside:
source: src/modules/esl-avatar
examples:
- avatar
---

{% mdRender 'src/modules/esl-avatar/README.md', 'intro' %}
243 changes: 243 additions & 0 deletions pages/views/examples/avatar.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
---
layout: content
title: Avatar
seoTitle: Avatar component examples based on ESL web components
name: Avatar
tags: [examples, beta]
icon: examples/avatar.svg
aside:
components:
- esl-avatar
---

{% macro avatarElement(class, src, username, loading) %}
<esl-avatar class="{{class}}"{% if src %} src="{{src}}"{% endif %}{% if username%} username="{{username}}"{% endif %}{% if loading %} loading="{{loading}}"{% endif %}></esl-avatar>
{% endmacro %}

{% macro avatarDemo(src, username, loading) %}
<div class="avatar-demo-wrapper">
{{ avatarElement('avatar-demo-1', src, username, loading) }}
{{ avatarElement('avatar-demo-2', src, username, loading) }}
{{ avatarElement('avatar-demo-3', src, username, loading) }}
{{ avatarElement('avatar-demo-4', src, username, loading) }}
</div>
{% endmacro %}

<style>
.avatar-demo-container {
justify-content: center;
margin-block: 40px;
}

.avatar-demo-wrapper {
display: flex;
flex-wrap: wrap;
justify-content: center;

esl-avatar {
margin: 0 5px;
}
}

.avatar-demo-1 {
background: #ffa500;
font-size: 12px;
font-weight: 300;
}

.avatar-demo-2 {
--esl-avatar-size: 60px;

background: #000;
font-size: 25px;
color: #ff0;
font-weight: 900;
}

.avatar-demo-3 {
--esl-avatar-size: 120px;

background: radial-gradient(circle, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 13%, rgba(0,212,255,1) 100%);
font-size: 60px;
color: #ff69b4;
border: 1px solid #ff0;
box-shadow: 0px 0px 10px 2px rgba(255, 255, 0, .2);
font-weight: 700;
}

.avatar-demo-4 {
--esl-avatar-size: 180px;

background: #f00;
font-size: 90px;
border: 9px solid #afeeee;
font-weight: 900;
}
</style>

<section class="row">
<div class="col-12">
<div class="row mb-4">
<div class="col-sm-12 col-md-6">
<div>
<h2>Avatar without image, text abbreviation only</h2>
{% code 'html' %}
<esl-avatar
username="ESL Developer">
</esl-avatar>
{% endcode %}
<p>ESL Avatar displays the user's initials. (The first letter from the first word of the username and the first letter from the second word if it exists.).</p>
</div>
</div>
<div class="col-sm-12 col-md-6 d-flex avatar-demo-container">
{{ avatarDemo('', 'ESL Developer', '') }}
</div>
</div>
<hr/>
<div class="row mb-4">
<div class="col-sm-12 col-md-6">
<div>
<h2>The component with JPEG image</h2>
{% code 'html' %}
<esl-avatar
username="Lead Developer"
src="/assets/avatar/user.jpg">
</esl-avatar>
{% endcode %}
<p>ESL Avatar displays an avatar image.</p>
</div>
</div>
<div class="col-sm-12 col-md-6 d-flex avatar-demo-container">
{{ avatarDemo('/assets/avatar/user.jpg', 'Lead Developer', '')}}
</div>
</div>
<hr/>
<div class="row mb-4">
<div class="col-sm-12 col-md-6">
<div>
<h2>Avatar with PNG image</h2>
{% code 'html' %}
<esl-avatar
username="Senior Developer"
src="/assets/avatar/user.png">
</esl-avatar>
{% endcode %}
<p>The component displays an avatar image.</p>
</div>
</div>
<div class="col-sm-12 col-md-6 d-flex avatar-demo-container">
{{ avatarDemo('/assets/avatar/user.png', 'Senior Developer', '')}}
</div>
</div>
<hr/>
<div class="row mb-4">
<div class="col-sm-12 col-md-6">
<div>
<h2>With transparent PNG image (3:2 ratio)</h2>
{% code 'html' %}
<esl-avatar
username="ESL Bot"
src="/assets/avatar/transparent.png">
</esl-avatar>
{% endcode %}
<p>It should be noted that the image is not square, but rectangular, the ratio is 3 to 2. As you can see, the component shows the image with the original ratio preserved in such a way that the image covers the entire plane of the component.</p>
</div>
</div>
<div class="col-sm-12 col-md-6 d-flex avatar-demo-container">
{{ avatarDemo('/assets/avatar/transparent.png', 'ESL Bot', '')}}
</div>
</div>
<hr/>
<div class="row mb-4">
<div class="col-sm-12 col-md-6">
<div>
<h2>With SVG image (and eager loading policy)</h2>
{% code 'html' %}
<esl-avatar
loading="eager"
username="Anonymous Developer"
src="/assets/avatar/user.svg">
</esl-avatar>
{% endcode %}
<p>The component displays an avatar image and the image will be loaded as soon as possible.</p>
</div>
</div>
<div class="col-sm-12 col-md-6 d-flex avatar-demo-container">
{{ avatarDemo('/assets/avatar/user.svg', 'Anonymous Developer', 'eager')}}
</div>
</div>
<hr/>
<div class="row mb-4">
<div class="col-sm-12 col-md-6">
<div>
<h2>With WEBP image (and lazy loading policy)</h2>
{% code 'html' %}
<esl-avatar
loading="lazy"
username="Junior Developer"
src="/assets/avatar/user.webp">
</esl-avatar>
{% endcode %}
<p>It will show the image, but the loading of the image by the browser will be delayed until it appears in the browser's viewport. The behavior is identical to the loading="lazy" mode for image tags. But lazy loading mode is enabled by default.</p>
</div>
</div>
<div class="col-sm-12 col-md-6 d-flex avatar-demo-container">
{{ avatarDemo('/assets/avatar/user.webp', 'Junior Developer', '')}}
</div>
</div>
<hr/>
<div class="row mb-4">
<div class="col-sm-12 col-md-6">
<div>
<h2>With transparent WEBP image (3:2 ratio)</h2>
{% code 'html' %}
<esl-avatar
username="Intern Developer"
src="/assets/avatar/transparent.webp">
</esl-avatar>
{% endcode %}
<p>It should be noted that the image is not square, but rectangular, the ratio is 3 to 2. As you can see, the component shows the image with the original ratio preserved in such a way that the image covers the entire plane of the component.</p>
</div>
</div>
<div class="col-sm-12 col-md-6 d-flex avatar-demo-container">
{{ avatarDemo('/assets/avatar/transparent.webp', 'Intern Developer', '')}}
</div>
</div>
<hr/>
<div class="row mb-4">
<div class="col-sm-12 col-md-6">
<div>
<h2>With animated WEBP image</h2>
{% code 'html' %}
<esl-avatar
username="Bored Developer"
src="/assets/avatar/animation.webp">
</esl-avatar>
{% endcode %}
<p>WOW!!! Live avatar!</p>
</div>
</div>
<div class="col-sm-12 col-md-6 d-flex avatar-demo-container">
{{ avatarDemo('/assets/avatar/animation.webp', 'Bored Developer', '')}}
</div>
</div>
<hr/>
<div class="row mb-4">
<div class="col-sm-12 col-md-6">
<div>
<h2>With image, but the image did not load</h2>
{% code 'html' %}
<esl-avatar
username="Non-existetnt Developer"
src="/assets/non-existent-image.png">
</esl-avatar>
{% endcode %}
<p>The component tries to load the image and switches to text mode displaying when it receives the error.</p>
</div>
</div>
<div class="col-sm-12 col-md-6 d-flex avatar-demo-container">
{{ avatarDemo('/assets/non-existent-image.png', 'Non-existetnt Developer', '')}}
</div>
</div>
</div>
</section>
2 changes: 2 additions & 0 deletions src/modules/all.less
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@
@import './esl-animate/core.less';

@import './esl-share/core.less';

@import './esl-avatar/core.less';
3 changes: 3 additions & 0 deletions src/modules/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export * from './esl-tooltip/core';
// Animate
export * from './esl-animate/core';

// Avatar
export * from './esl-avatar/core';

// Related Target Mixin
export * from './esl-related-target/core';

Expand Down
32 changes: 32 additions & 0 deletions src/modules/esl-avatar/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# [ESL](../../../) Avatar

Version: *1.0.0-beta*.

Authors: *Dmytro Shovchko*.

***Important Notice: the component is under beta version, it is tested and ready to use but be aware of its potential critical API changes.***

<a name="intro"></a>

**ESLAvatar** is a versatile UI element representing a user with profile pictures or initials.

The component works as follows. If the consumer has specified the `src` attribute with the profile picture URL, the component will try to display the image in the inner content.

If the URL of the picture is not specified or an error occurs when loading the image, the component will switch to text mode. In text mode, it displays the initials from the username or in simple words, just the first letters of each word in the username. The length of this username abbreviation is limited by the `abbr-length` parameter and defaults to 2.

### Attributes:

- `abbr-length` - the limit number of letters to be displayed in text-only mode
- `loading` - policy of loading image that is outside of the viewport
- `src` - URL of the avatar picture
- `username` - the name of the user for whom the avatar is displayed.

### API

- `abbr` - getter that returns an abbreviation to display in text-only mode and for alt property of image
- `init` - initializes inner content of the component.

### Events

- `esl:avatar:changed` - event to dispatch on change of ESLAvatar

1 change: 1 addition & 0 deletions src/modules/esl-avatar/core.less
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import './core/esl-avatar.less';
1 change: 1 addition & 0 deletions src/modules/esl-avatar/core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './core/esl-avatar';
29 changes: 29 additions & 0 deletions src/modules/esl-avatar/core/esl-avatar.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
esl-avatar {
display: flex;
align-items: center;
justify-content: center;
transition: opacity 0.3s ease-in-out;
opacity: 0;
border-radius: 50%;
width: var(--esl-avatar-size, 32px);
min-width: var(--esl-avatar-size, 32px);
height: var(--esl-avatar-size, 32px);
min-height: var(--esl-avatar-size, 32px);
overflow: hidden;
text-transform: uppercase;
line-height: 1em;

&[with-image] {
background: transparent;
}

&[ready] {
opacity: 1;
}

.esl-avatar-img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
Loading