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

ACS-8315: avatar component #9931

Merged
merged 9 commits into from
Jul 9, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
13 changes: 10 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 |
Expand Down
1 change: 1 addition & 0 deletions docs/core/components/avatar.component.md
1 change: 1 addition & 0 deletions docs/core/components/button.component.md
7 changes: 7 additions & 0 deletions lib/core/src/lib/avatar/avatar.component.html
Original file line number Diff line number Diff line change
@@ -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>
78 changes: 78 additions & 0 deletions lib/core/src/lib/avatar/avatar.component.md
Original file line number Diff line number Diff line change
@@ -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. |
```
20 changes: 20 additions & 0 deletions lib/core/src/lib/avatar/avatar.component.scss
Original file line number Diff line number Diff line change
@@ -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;
}
89 changes: 89 additions & 0 deletions lib/core/src/lib/avatar/avatar.component.spec.ts
Original file line number Diff line number Diff line change
@@ -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');
});
});
46 changes: 46 additions & 0 deletions lib/core/src/lib/avatar/avatar.component.ts
Original file line number Diff line number Diff line change
@@ -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');
DenysVuika marked this conversation as resolved.
Show resolved Hide resolved

@HostBinding('style.--adf-avatar-cursor')
@Input()
cursor = getComputedStyle(document.documentElement).getPropertyValue('--adf-avatar-cursor');
}
1 change: 1 addition & 0 deletions lib/core/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Loading