Skip to content
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
31 changes: 23 additions & 8 deletions docs/components-api/avatar.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,28 @@

# ExtraAvatar

> ✅ **Реализован**: `ExtraAvatarComponent` (`@cdek-it/angular-ui-kit`) соответствует спецификации.

Представление пользователя.

| Свойство | Описание | Типизация |
| -------- | --------------------------- | ------------------------- |
| `size` | размер аватара | `base \| large \| xlarge` |
| `shape` | форма | `square \| circle` |
| `image` | изображение | `string` |
| `label` | текст/инициалы | `string` |
| `icon` | класс иконки tabler icon | `string` |
| `badge` | отображать значок (`Badge`) | `string` |
| Свойство | Описание | Типизация |
| ---------- | ----------------------------------- | ------------------------------------------------- |
| `size` | размер аватара | `base \| large \| xlarge` |
| `shape` | форма | `square \| circle` |
| `image` | изображение | `string` |
| `label` | текст/инициалы | `string` |
| `icon` | класс иконки tabler icon | `string` |
| `badge` | отображать значок (`Badge`) | `string` |
| `severity` | цветовая схема значка (при `badge`) | `primary \| success \| info \| warning \| danger` |

# ExtraAvatarGroup

Группа аватаров с перекрытием (стек). Дочерние `ExtraAvatar` передаются как есть — своих свойств у группы нет.

```html
<extra-avatar-group>
<extra-avatar image="..." shape="circle"></extra-avatar>
<extra-avatar image="..." shape="circle"></extra-avatar>
<extra-avatar label="+2" shape="circle"></extra-avatar>
</extra-avatar-group>
```
41 changes: 33 additions & 8 deletions src/lib/components/avatar/avatar.component.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
import { ChangeDetectionStrategy, Component, HostBinding, Input } from '@angular/core';
import { NgTemplateOutlet } from '@angular/common';
import { Avatar } from 'primeng/avatar';
import { AvatarGroup } from 'primeng/avatargroup';
import { OverlayBadge } from 'primeng/overlaybadge';
import { ExtraBadgeSeverity } from '@cdek-it/angular-ui-kit/components/badge';

export type ExtraAvatarSize = 'base' | 'large' | 'xlarge';
export type ExtraAvatarShape = 'square' | 'circle';

type PrimeOverlayBadgeSeverity = 'secondary' | 'info' | 'success' | 'warn' | 'danger' | 'contrast' | null | undefined;

@Component({
selector: 'extra-avatar',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [Avatar],
imports: [Avatar, OverlayBadge, NgTemplateOutlet],
template: `
<p-avatar
[label]="label || undefined"
[icon]="icon || undefined"
[image]="image || undefined"
[size]="primeSize"
[shape]="shape"
></p-avatar>
@if (badge) {
<!-- size бейджу не передаём: по макету значок одного размера на всех размерах аватара,
а OverlayBadge.size к тому же deprecated и внутрь p-badge не прокидывается. -->
<p-overlay-badge [value]="badge" [severity]="primeSeverity">
<ng-container [ngTemplateOutlet]="avatarTpl" />
</p-overlay-badge>
} @else {
<ng-container [ngTemplateOutlet]="avatarTpl" />
}

<ng-template #avatarTpl>
<p-avatar
[label]="label || undefined"
[icon]="icon || undefined"
[image]="image || undefined"
[size]="primeSize"
[shape]="shape"
></p-avatar>
</ng-template>
`
})
export class ExtraAvatarComponent {
Expand All @@ -26,6 +43,8 @@ export class ExtraAvatarComponent {
@Input() image = '';
@Input() size: ExtraAvatarSize = 'base';
@Input() shape: ExtraAvatarShape = 'square';
@Input() badge: string | undefined;
@Input() severity: ExtraBadgeSeverity = 'primary';

@HostBinding('class') get hostClass(): string {
const classes = ['ui-avatar'];
Expand All @@ -37,6 +56,12 @@ export class ExtraAvatarComponent {
get primeSize(): 'large' | 'xlarge' | undefined {
return this.size === 'base' ? undefined : this.size;
}

get primeSeverity(): PrimeOverlayBadgeSeverity {
if (this.severity === 'primary') return null;
if (this.severity === 'warning') return 'warn';
return this.severity as Exclude<PrimeOverlayBadgeSeverity, null | undefined | 'warn'>;
}
}

@Component({
Expand Down
55 changes: 32 additions & 23 deletions src/lib/components/avatar/avatar.figma.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,26 @@ figma:
componentKey: 'fe504adcf02d8f8922f04f6ccb8bf3777ad701d9'
name: '<Avatar>'
status: stable
updated: '2026-06-22'
updated: '2026-09-29'
---

## Overview

`ExtraAvatar` — компонент для отображения пользователя или сущности. Поддерживает три способа представления содержимого: текстовую метку, иконку или изображение. Оборачивает PrimeNG `p-avatar` и расширяет его собственными размерами и формами.
`ExtraAvatar` — компонент для отображения пользователя или сущности. Поддерживает три способа представления содержимого: текстовую метку, иконку или изображение. Оборачивает PrimeNG `p-avatar` и расширяет его собственными размерами, формами и встроенным значком (`badge`, через PrimeNG `p-overlay-badge`).

Компонент соответствует Figma-компоненту `<Avatar>` (nodeId `36:1365`). Figma-свойство `type` (`image | icon | label`) не маппируется в отдельный инпут — способ представления выбирается тем, какой из инпутов `image`, `icon` или `label` задан (см. раздел Props mapping).

## Props mapping

| Свойство | Тип | По умолчанию | Описание |
|----------|-----|--------------|---------|
| `label` | `string` | `''` | Текстовая метка внутри аватара — соответствует Figma-свойству `type=label` |
| `icon` | `string` | `''` | CSS-класс иконки (например `'ti ti-user'`) — соответствует Figma-свойству `type=icon` и `change-icon` (INSTANCE_SWAP); доступные иконки — [icons.md](../../figma-code-connect/icons.md) |
| `image` | `string` | `''` | URL изображения — соответствует Figma-свойству `type=image` |
| `size` | `'normal' \| 'large' \| 'xlarge'` | `'normal'` | Размер аватара — соответствует Figma-свойству `size` (Figma `base` → код `normal`) |
| `shape` | `'square' \| 'circle'` | `'square'` | Форма аватара — соответствует Figma-свойству `shape` |

Figma-свойство `show-badge` (BOOLEAN) не имеет отдельного инпута: бейдж навешивается снаружи через PrimeNG `p-overlay-badge`, оборачивающий `extra-avatar` (см. раздел Variants).
| Свойство | Тип | По умолчанию | Описание |
| ---------- | ----------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label` | `string` | `''` | Текстовая метка внутри аватара — соответствует Figma-свойству `type=label` |
| `icon` | `string` | `''` | CSS-класс иконки (например `'ti ti-user'`) — соответствует Figma-свойству `type=icon` и `change-icon` (INSTANCE_SWAP); доступные иконки — [icons.md](../../figma-code-connect/icons.md) |
| `image` | `string` | `''` | URL изображения — соответствует Figma-свойству `type=image` |
| `size` | `'base' \| 'large' \| 'xlarge'` | `'base'` | Размер аватара — соответствует Figma-свойству `size` |
| `shape` | `'square' \| 'circle'` | `'square'` | Форма аватара — соответствует Figma-свойству `shape` |
| `badge` | `string \| undefined` | `undefined` | Текст/число значка — соответствует Figma-свойству `show-badge`; при задании оборачивает аватар в PrimeNG `p-overlay-badge` |
| `severity` | `'primary' \| 'success' \| 'info' \| 'warning' \| 'danger'` | `'primary'` | Цветовая схема значка (при заданном `badge`) — та же шкала, что у [ExtraBadge](../badge/badge.figma.md) |

## Variants

Expand Down Expand Up @@ -72,23 +72,29 @@ Figma: size=large, shape=circle, type=label
Figma: size=xlarge, shape=circle, type=image

```html
<extra-avatar
image="/assets/images/avatar/avatar.png"
size="xlarge"
shape="circle"
></extra-avatar>
<extra-avatar image="/assets/images/avatar/avatar.png" size="xlarge" shape="circle"></extra-avatar>
```

### С бейджем (show-badge)

Figma: size=xlarge, shape=square, type=label, show-badge=true

Бейдж навешивается снаружи через `p-overlay-badge`; цветовая схема — токены [tokens.md](../../figma-code-connect/tokens.md).
Компонент сам оборачивает себя в PrimeNG `p-overlay-badge`, когда задан `badge`.

```html
<extra-avatar label="U" size="xlarge" badge="4" severity="danger"></extra-avatar>
```

### Группа аватаров (ExtraAvatarGroup)

Не описана отдельным Figma-компонентом, но является полезной композицией `<extra-avatar>` — стек аватаров с перекрытием.

```html
<p-overlay-badge value="4" severity="danger">
<extra-avatar label="U" size="xlarge"></extra-avatar>
</p-overlay-badge>
<extra-avatar-group>
<extra-avatar image="/assets/images/avatar/avatar.png" shape="circle"></extra-avatar>
<extra-avatar image="/assets/images/avatar/avatar.png" shape="circle"></extra-avatar>
<extra-avatar label="+2" shape="circle"></extra-avatar>
</extra-avatar-group>
```

## Slots
Expand All @@ -101,18 +107,21 @@ Figma: size=xlarge, shape=square, type=label, show-badge=true
- [Токены](../../figma-code-connect/tokens.md) — цветовые токены бейджа и фона
- [Conventions](../../figma-code-connect/conventions.md) — соглашения маппинга Figma → Angular
- [ExtraTag](../tag/tag.figma.md) — близкий по назначению компонент-метка
- [ExtraBadge](../badge/badge.figma.md) — самостоятельный компонент-значок (та же шкала `severity`)
- [ExtraButton](../button/button.figma.md) — пример компонента с навешиваемым бейджем

## Do / Don't

**Do:**

- Задавайте ровно один из инпутов `label`, `icon` или `image` — он определяет Figma-свойство `type`
- Для иконки используйте классы из справочника [icons.md](../../figma-code-connect/icons.md)
- Для круглых аватаров с изображением задавайте `shape="circle"` — изображение обрежется по кругу
- Бейдж навешивайте снаружи через `p-overlay-badge`, оборачивающий `extra-avatar`
- Задавайте `badge` для значка поверх аватара — компонент сам оборачивает себя в `p-overlay-badge`, ничего оборачивать вручную не нужно
- Используйте `<extra-avatar-group>` для стека перекрывающихся аватаров

**Don't:**

- Не задавайте одновременно `image` и `label` или `image` и `icon` — представление станет неоднозначным
- Не инлайньте CSS-классы иконок вручную — используйте справочник [icons.md](../../figma-code-connect/icons.md)
- Не используйте `size="base"` — в коде базовый размер называется `normal` (Figma `base` ↔ код `normal`)
- Не пытайтесь задать бейдж инпутом компонента — отдельного инпута нет, используйте `p-overlay-badge`
- Не оборачивайте `<extra-avatar>` в `p-overlay-badge` вручную — используйте `badge`/`severity`, компонент сделает это сам
8 changes: 8 additions & 0 deletions src/lib/providers/prime-preset/tokens/components/avatar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,17 @@ export const avatarCss = ({ dt }: { dt: (token: string) => string }): string =>

.p-avatar.p-avatar-circle {
border-radius: ${dt('avatar.extend.circle.borderRadius')};
}

/* Изображение — Fill блока: обрезаем по радиусу и для square, и для circle. */
.p-avatar {
overflow: hidden;
}

.p-avatar img {
object-fit: cover;
}

.p-overlaybadge.p-overlaybadge {
width: fit-content;
}
Expand Down
3 changes: 1 addition & 2 deletions src/lib/providers/prime-preset/tokens/tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -1379,7 +1379,6 @@
},
"avatar": {
"extend": {
"borderColor": "{color.border.neutral.strong}",
"circle": {
"borderRadius": "{dimension.borderRadius.max}"
}
Expand All @@ -1390,7 +1389,7 @@
"fontSize": "{fonts.fontSize.300}",
"color": "{color.fg.on.brand.default}",
"background": "{color.bg.brand.strong.default}",
"borderRadius": "{dimension.borderRadius.400}"
"borderRadius": "{dimension.borderRadius.350}"
},
"icon": {
"size": "{dimension.size.450}"
Expand Down
Loading
Loading