ACS-8315: avatar component (#9931)

This commit is contained in:
Denys Vuika 2024-07-09 17:58:41 -04:00 committed by GitHub
parent eaa489ae8d
commit a0b82ad887
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 265 additions and 3 deletions

View File

@ -18,6 +18,18 @@
<app-search-bar></app-search-bar>
<app-shell-user-info [menuPositionX]="'before'" [menuPositionY]="'above'"></app-shell-user-info>
<adf-avatar
size="32px"
src="https://avatars.githubusercontent.com/u/503991?v=4&size=64"
initials="DV"
tooltip="Denys Vuika"
cursor="pointer"
[matMenuTriggerFor]="userMenu">
</adf-avatar>
<mat-menu #userMenu="matMenu">
<button mat-menu-item>Item 1</button>
<button mat-menu-item>Item 2</button>
</mat-menu>
</adf-layout-header>
</ng-template>
</adf-sidenav-layout-header>

View File

@ -30,10 +30,8 @@ A few other pages of information are also available:
- The [Release notes](release-notes/README.md) section has details of all
the features introduced and bugs fixed with each release.
- The [Version compatibility](compatibility.md) page shows which versions
of Alfresco's backend servies (ACS and APS) are compatible with each released
of Alfresco backend services (ACS and APS) are compatible with each released
version of ADF.
- The [Roadmap](roadmap.md)
contains a preview of features we hope to release in future versions of ADF.
- The [License info](license-info/README.md) section lists the third-party libraries used by ADF along with links to their Open Source licenses.
- The [Vulnerability](vulnerability/README.md) section lists the third-party
libraries known vulnerability.
@ -79,6 +77,15 @@ for more information about installing and using the source code.
<!--core start-->
### Primitives
A collection of Angular components for generic use.
| Name | Description |
|-----------------------------------------------|------------------------------|
| [Avatar](core/components/avatar.component.md) | Displays user avatars. |
| [Button](core/components/button.component.md) | A standard button component. |
### Components
| Name | Description | Source link |

View File

@ -0,0 +1 @@
../../../lib/core/src/lib/avatar/avatar.component.md

View File

@ -0,0 +1 @@
../../../lib/core/src/lib/button/button.component.md

View File

@ -0,0 +1,7 @@
<div class="adf-avatar">
<img *ngIf="src; else initialsTemplate" class="adf-avatar__image" [src]="src" [alt]="initials" [title]="tooltip" />
</div>
<ng-template #initialsTemplate>
<div class="adf-avatar__image adf-avatar__initials" [title]="tooltip">{{ initials }}</div>
</ng-template>

View File

@ -0,0 +1,78 @@
# Avatar Component
`standalone`, `component`
The Avatar component is a simple component that can be used to display user avatars.
## Usage
Displaying an avatar with an image and initials fallback:
```html
<adf-avatar
size="32px"
src="https://avatars.githubusercontent.com/u/503991?v=4&size=64"
initials="DV"
tooltip="Denys Vuika"
>
</adf-avatar>
```
Integrating with context menu:
```html
<adf-avatar
size="32px"
src="https://avatars.githubusercontent.com/u/503991?v=4&size=64"
initials="DV"
tooltip="Denys Vuika"
cursor="pointer"
[matMenuTriggerFor]="userMenu">
</adf-avatar>
<mat-menu #userMenu="matMenu">
<button mat-menu-item>Item 1</button>
<button mat-menu-item>Item 2</button>
</mat-menu>
```
## API
Import the following standalone components:
```typescript
import { AvatarComponent } from '@alfresco/adf-core';
```
## Properties
| Name | Type | Default | Description |
|------------|--------|---------|--------------------------------------------------------|
| `size` | string | `32px` | The size of the avatar. |
| `src` | string | | The URL of the image to display. |
| `initials` | string | | The initials to display if the image is not available. |
| `tooltip` | string | | The tooltip to display when hovering over the avatar. |
| `cursor` | string | `auto` | The cursor style. |
## Theming
The following CSS classes are available for theming:
| Name | Description |
|------------------------|-----------------------|
| `adf-avatar` | The host element. |
| `adf-avatar__image` | The image element. |
| `adf-avatar__initials` | The initials element. |
### CSS Variables
| Name | Default | Description |
|---------------------------------|-----------|-------------------------------------|
| `--adf-avatar-size` | `32px` | The size of the avatar. |
| `--adf-avatar-border-radius` | `50%` | The border radius of the avatar. |
| `--adf-avatar-background-color` | `#f3f3f3` | The background color of the avatar. |
| `--adf-avatar-color` | `#333` | The text color of the initials. |
| `--adf-avatar-font-size` | `14px` | The font size of the initials. |
| `--adf-avatar-font-weight` | `500` | The font weight of the initials. |
| `--adf-avatar-cursor` | `auto` | The cursor style. |
```

View File

@ -0,0 +1,20 @@
.adf-avatar {
display: flex;
}
.adf-avatar__image {
cursor: var(--adf-avatar-cursor, auto);
display: inline-block;
overflow: hidden;
line-height: 1;
border-radius: var(--adf-avatar-border-radius, 50%);
width: var(--adf-avatar-size, 32px);
height: var(--adf-avatar-size, 32px);
color: var(--adf-avatar-color, #333);
background-color: var(--adf-avatar-background-color, #f3f3f3);
box-shadow: 0 0 0 1px var(--adf-avatar-border-color, rgba(31, 35, 40, 0.15));
font-size: var(--adf-avatar-font-size, 14px);
font-weight: var(--adf-avatar-font-weight, 500);
text-align: center;
align-content: center;
}

View File

@ -0,0 +1,89 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AvatarComponent } from '@alfresco/adf-core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
describe('AvatarComponent', () => {
let component: AvatarComponent;
let fixture: ComponentFixture<AvatarComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AvatarComponent]
}).compileComponents();
fixture = TestBed.createComponent(AvatarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should display initials when src is not provided', () => {
component.src = '';
fixture.detectChanges();
const avatarElement: HTMLElement = fixture.nativeElement.querySelector('.adf-avatar__initials');
expect(avatarElement.textContent).toContain(component.initials);
});
it('should display image when src is provided', () => {
component.src = 'path/to/image.jpg';
fixture.detectChanges();
const imgElement: HTMLImageElement = fixture.nativeElement.querySelector('.adf-avatar__image');
expect(imgElement.src).toContain(component.src);
});
it('should use default initials when not provided', () => {
fixture.detectChanges();
const avatarElement: HTMLElement = fixture.nativeElement.querySelector('.adf-avatar__initials');
expect(avatarElement.textContent).toContain('U');
});
it('should use custom initials', () => {
component.initials = 'DV';
fixture.detectChanges();
const avatarElement: HTMLElement = fixture.nativeElement.querySelector('.adf-avatar__initials');
expect(avatarElement.textContent).toContain('DV');
});
it('should apply custom size style when size is provided', () => {
component.size = '48px';
fixture.detectChanges();
const style = getComputedStyle(fixture.nativeElement.querySelector('.adf-avatar__image'));
expect(style.width).toBe('48px');
expect(style.height).toBe('48px');
});
it('should apply custom cursor style when cursor is provided', () => {
component.cursor = 'pointer';
fixture.detectChanges();
const style = getComputedStyle(fixture.nativeElement.querySelector('.adf-avatar__image'));
expect(style.cursor).toBe('pointer');
});
it('should display tooltip when provided', () => {
component.tooltip = 'User Tooltip';
fixture.detectChanges();
const avatarElement: HTMLElement = fixture.nativeElement.querySelector('.adf-avatar__image');
expect(avatarElement.getAttribute('title')).toBe('User Tooltip');
});
});

View File

@ -0,0 +1,46 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, HostBinding, Input, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'adf-avatar',
standalone: true,
imports: [CommonModule],
templateUrl: './avatar.component.html',
styleUrls: ['./avatar.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class AvatarComponent {
@Input()
src: string;
@Input()
initials: string = 'U';
@Input()
tooltip: string = '';
@HostBinding('style.--adf-avatar-size')
@Input()
size = getComputedStyle(document.documentElement).getPropertyValue('--adf-avatar-size');
@HostBinding('style.--adf-avatar-cursor')
@Input()
cursor = getComputedStyle(document.documentElement).getPropertyValue('--adf-avatar-cursor');
}

View File

@ -16,6 +16,7 @@
*/
export * from './lib/about/index';
export * from './lib/avatar/avatar.component';
export * from './lib/button/button.component';
export * from './lib/viewer/index';
export * from './lib/toolbar/index';