diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.html b/demo-shell/src/app/components/app-layout/app-layout.component.html index 30b7d1de977..31c840191d1 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.html +++ b/demo-shell/src/app/components/app-layout/app-layout.component.html @@ -18,6 +18,18 @@ + + + + + + diff --git a/docs/README.md b/docs/README.md index 73ff140a4e9..1241ad9631f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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. +### 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 | diff --git a/docs/core/components/avatar.component.md b/docs/core/components/avatar.component.md new file mode 120000 index 00000000000..732acc2e390 --- /dev/null +++ b/docs/core/components/avatar.component.md @@ -0,0 +1 @@ +../../../lib/core/src/lib/avatar/avatar.component.md \ No newline at end of file diff --git a/docs/core/components/button.component.md b/docs/core/components/button.component.md new file mode 120000 index 00000000000..f5978fde61e --- /dev/null +++ b/docs/core/components/button.component.md @@ -0,0 +1 @@ +../../../lib/core/src/lib/button/button.component.md \ No newline at end of file diff --git a/lib/core/src/lib/avatar/avatar.component.html b/lib/core/src/lib/avatar/avatar.component.html new file mode 100644 index 00000000000..88e79302303 --- /dev/null +++ b/lib/core/src/lib/avatar/avatar.component.html @@ -0,0 +1,7 @@ +
+ +
+ + +
{{ initials }}
+
diff --git a/lib/core/src/lib/avatar/avatar.component.md b/lib/core/src/lib/avatar/avatar.component.md new file mode 100644 index 00000000000..473626f80f4 --- /dev/null +++ b/lib/core/src/lib/avatar/avatar.component.md @@ -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 + + +``` + +Integrating with context menu: + +```html + + + + + + + +``` + +## 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. | +``` diff --git a/lib/core/src/lib/avatar/avatar.component.scss b/lib/core/src/lib/avatar/avatar.component.scss new file mode 100644 index 00000000000..67e69728c52 --- /dev/null +++ b/lib/core/src/lib/avatar/avatar.component.scss @@ -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; +} diff --git a/lib/core/src/lib/avatar/avatar.component.spec.ts b/lib/core/src/lib/avatar/avatar.component.spec.ts new file mode 100644 index 00000000000..07bd1623f5b --- /dev/null +++ b/lib/core/src/lib/avatar/avatar.component.spec.ts @@ -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; + + 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'); + }); +}); diff --git a/lib/core/src/lib/avatar/avatar.component.ts b/lib/core/src/lib/avatar/avatar.component.ts new file mode 100644 index 00000000000..9a868c769ae --- /dev/null +++ b/lib/core/src/lib/avatar/avatar.component.ts @@ -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'); +} diff --git a/lib/core/src/public-api.ts b/lib/core/src/public-api.ts index 7105f0fdd68..84ce1ca93f9 100644 --- a/lib/core/src/public-api.ts +++ b/lib/core/src/public-api.ts @@ -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';