Skip to content

Commit

Permalink
feat(kit): support fallback for avatar when img not found by `ava…
Browse files Browse the repository at this point in the history
…tarUrl` (#4243)
  • Loading branch information
splincode authored Apr 21, 2023
1 parent 212b670 commit 68f4922
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 13 deletions.
16 changes: 16 additions & 0 deletions projects/demo/src/modules/components/avatar/avatar.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Component} from '@angular/core';
import {SafeHtml} from '@angular/platform-browser';
import {changeDetection} from '@demo/emulate/change-detection';
import {RawLoaderContent, TuiDocExample} from '@taiga-ui/addon-doc';
import {TuiSizeXXL, TuiSizeXXS} from '@taiga-ui/core';
Expand Down Expand Up @@ -47,12 +48,27 @@ export class ExampleTuiAvatarComponent {
HTML: import('./examples/5/index.html?raw'),
};

readonly example6: TuiDocExample = {
TypeScript: import('./examples/6/index.ts?raw'),
HTML: import('./examples/6/index.html?raw'),
LESS: import('./examples/6/index.less?raw'),
};

readonly avatarUrlVariants: readonly string[] = [
'https://ng-web-apis.github.io/dist/assets/images/web-api.svg',
'https://taiga-ui.dev/assets/images/test-not-found.png',
];

readonly fallbackVariants: ReadonlyArray<SafeHtml | string> = [
'tuiIconUserLarge',
'<svg enable-background="new 0 0 32 32" height="32px" viewBox="0 0 32 32" width="32px"' +
' xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="Error_x2C__lost_x2C__no_page_x2C__not_found"><g><g><g><circle cx="7.5" cy="5.5" fill="#263238" r="0.5"/><circle cx="5.5" cy="5.5" fill="#263238" r="0.5"/><circle cx="3.5" cy="5.5" fill="#263238" r="0.5"/><path d="M30.5,8h-29C1.224,8,1,7.776,1,7.5S1.224,7,1.5,7h29C30.776,7,31,7.224,31,7.5S30.776,8,30.5,8z" fill="#263238"/><path d="M29.5,29h-27C1.673,29,1,28.327,1,27.5v-23C1,3.673,1.673,3,2.5,3h27C30.327,3,31,3.673,31,4.5v23 C31,28.327,30.327,29,29.5,29z M2.5,4C2.224,4,2,4.225,2,4.5v23C2,27.775,2.224,28,2.5,28h27c0.276,0,0.5-0.225,0.5-0.5v-23 C30,4.225,29.776,4,29.5,4H2.5z" fill="#263238"/></g></g></g><g><path d="M24.5,24c-0.276,0-0.5-0.224-0.5-0.5V21h-3.5c-0.163,0-0.315-0.079-0.409-0.212s-0.117-0.303-0.062-0.456 l2.5-7C22.6,13.133,22.789,13,23,13h1.5c0.276,0,0.5,0.224,0.5,0.5V20h0.5c0.276,0,0.5,0.224,0.5,0.5S25.776,21,25.5,21H25v2.5 C25,23.776,24.776,24,24.5,24z M21.209,20H24v-6h-0.647L21.209,20z" fill="#263238"/><path d="M10.5,24c-0.276,0-0.5-0.224-0.5-0.5V21H6.5c-0.163,0-0.315-0.079-0.409-0.212s-0.117-0.303-0.062-0.456 l2.5-7C8.6,13.133,8.789,13,9,13h1.5c0.276,0,0.5,0.224,0.5,0.5V20h0.5c0.276,0,0.5,0.224,0.5,0.5S11.776,21,11.5,21H11v2.5 C11,23.776,10.776,24,10.5,24z M7.209,20H10v-6H9.353L7.209,20z" fill="#263238"/><path d="M17.5,24h-3c-0.827,0-1.5-0.673-1.5-1.5v-8c0-0.827,0.673-1.5,1.5-1.5h3c0.827,0,1.5,0.673,1.5,1.5v8 C19,23.327,18.327,24,17.5,24z M14.5,14c-0.276,0-0.5,0.225-0.5,0.5v8c0,0.275,0.224,0.5,0.5,0.5h3c0.276,0,0.5-0.225,0.5-0.5v-8 c0-0.275-0.224-0.5-0.5-0.5H14.5z" fill="#263238"/></g></g></svg>',
];

avatarUrl: string | null = null;

fallback: SafeHtml | string | null = this.fallbackVariants[0];

text = 'daenerys targaryen';

rounded = false;
Expand Down
2 changes: 2 additions & 0 deletions projects/demo/src/modules/components/avatar/avatar.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {TuiAvatarExample2} from './examples/2';
import {TuiAvatarExample3} from './examples/3';
import {TuiAvatarExample4} from './examples/4';
import {TuiAvatarExample5} from './examples/5';
import {TuiAvatarExample6} from './examples/6';

@NgModule({
imports: [
Expand All @@ -27,6 +28,7 @@ import {TuiAvatarExample5} from './examples/5';
TuiAvatarExample3,
TuiAvatarExample4,
TuiAvatarExample5,
TuiAvatarExample6,
],
exports: [ExampleTuiAvatarComponent],
})
Expand Down
20 changes: 19 additions & 1 deletion projects/demo/src/modules/components/avatar/avatar.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@
</tui-notification>
<tui-avatar-example-5></tui-avatar-example-5>
</tui-doc-example>

<tui-doc-example
id="fallback"
heading="Fallback"
[content]="example6"
>
<tui-avatar-example-6></tui-avatar-example-6>
</tui-doc-example>
</ng-template>

<ng-template pageTab>
Expand All @@ -73,6 +81,7 @@
[rounded]="rounded"
[size]="size"
[autoColor]="autoColor"
[fallback]="fallback"
[style.--tui-avatar-color]="color"
[style.--tui-avatar-background]="background"
></tui-avatar>
Expand All @@ -84,7 +93,7 @@
documentationPropertyMode="input"
[(documentationPropertyValue)]="autoColor"
>
Autocolor if there is no image
Auto color if there is no image
</ng-template>
<ng-template
documentationPropertyName="avatarUrl"
Expand All @@ -95,6 +104,15 @@
>
Avatar URL or Taiga UI icon name
</ng-template>
<ng-template
documentationPropertyName="fallback"
documentationPropertyType="string | SafeHtml | null"
documentationPropertyMode="input"
[documentationPropertyValues]="fallbackVariants"
[(documentationPropertyValue)]="fallback"
>
Avatar URL or Taiga UI icon name
</ng-template>
<ng-template
documentationPropertyName="rounded"
documentationPropertyType="boolean"
Expand Down
12 changes: 12 additions & 0 deletions projects/demo/src/modules/components/avatar/examples/6/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<tui-avatar
new
class="avatar"
[avatarUrl]="waterplea"
></tui-avatar>

<tui-avatar
new
fallback="tuiIconUserLarge"
class="tui-space_left-3 avatar"
[avatarUrl]="wrongUrl"
></tui-avatar>
16 changes: 16 additions & 0 deletions projects/demo/src/modules/components/avatar/examples/6/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@import 'taiga-ui-local';

:host {
display: flex;
}

.avatar {
.shadow(1);

background: transparent;
border: 1px solid;

&:hover {
.shadow(5);
}
}
15 changes: 15 additions & 0 deletions projects/demo/src/modules/components/avatar/examples/6/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {Component} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';

@Component({
selector: 'tui-avatar-example-6',
templateUrl: './index.html',
styleUrls: ['./index.less'],
changeDetection,
encapsulation,
})
export class TuiAvatarExample6 {
readonly waterplea = 'https://avatars.githubusercontent.com/u/11832552?v=4';
readonly wrongUrl = 'https://taiga-ui.dev/assets/images/test-not-found.png';
}
37 changes: 25 additions & 12 deletions projects/kit/components/avatar/avatar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
Inject,
Input,
} from '@angular/core';
import {SafeResourceUrl} from '@angular/platform-browser';
import {tuiDefaultProp, tuiIsString, tuiRequiredSetter} from '@taiga-ui/cdk';
import {tuiSizeBigger} from '@taiga-ui/core';
import {SafeHtml, SafeResourceUrl} from '@angular/platform-browser';
import {tuiDefaultProp, tuiIsString, tuiPure, tuiRequiredSetter} from '@taiga-ui/cdk';
import {tuiSizeBigger, TuiSizeXXL, TuiSizeXXS} from '@taiga-ui/core';
import {tuiStringHashToHsl} from '@taiga-ui/kit/utils/format';

import {TUI_AVATAR_OPTIONS, TuiAvatarOptions} from './avatar-options';
Expand Down Expand Up @@ -35,6 +35,10 @@ export class TuiAvatarComponent {
@tuiDefaultProp()
text = '';

@Input()
@tuiDefaultProp()
fallback: SafeHtml | string | null = null;

@Input()
@tuiDefaultProp()
autoColor: boolean = this.options.autoColor;
Expand Down Expand Up @@ -64,16 +68,16 @@ export class TuiAvatarComponent {
return tuiIsString(this.avatarUrl) && !!this.avatarUrl?.startsWith('tuiIcon');
}

get computedText(): string {
if (this.hasAvatar || this.iconAvatar || this.text === '') {
return '';
}

const words = this.text.split(' ');
get useFallback(): boolean {
return (
!!this.fallback && !!this.avatarUrl && !this.isUrlValid && !this.text.length
);
}

return words.length > 1 && tuiSizeBigger(this.size)
? words[0].slice(0, 1) + words[1].slice(0, 1)
: words[0].slice(0, 1);
get computedText(): string {
return this.hasAvatar || this.iconAvatar || this.text === ''
? ''
: this.getSlicedText(this.text, this.size);
}

get stringAvatar(): string {
Expand All @@ -83,4 +87,13 @@ export class TuiAvatarComponent {
onError(): void {
this.isUrlValid = false;
}

@tuiPure
private getSlicedText(text: string, size: TuiSizeXXL | TuiSizeXXS): string {
const words = text.split(' ');

return words.length > 1 && tuiSizeBigger(size)
? words[0].slice(0, 1) + words[1].slice(0, 1)
: words[0].slice(0, 1);
}
}
5 changes: 5 additions & 0 deletions projects/kit/components/avatar/avatar.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
[src]="avatarUrl || ''"
(error)="onError()"
/>
<tui-svg
*ngIf="useFallback"
class="t-icon"
[src]="fallback!"
></tui-svg>
<tui-svg
*ngIf="stringAvatar"
class="t-icon"
Expand Down

0 comments on commit 68f4922

Please sign in to comment.