GrAvatar

  • ядро
  • Данные
  • API · 8 props

Берут, когда человека или сущность узнают по картинке.

import { GrAvatar } from '@feugene/granularity/components/GrAvatar'

Обзор

Когда брать

  • человека или сущность узнают по картинке — список участников, автор комментария, владелец задачи;
  • картинки может не быть — откат идёт по цепочке: src, fallbackSrc, инициалы из name, слот;
  • нужен статус присутствия — точка на аватаре вместо отдельного значка рядом;
  • участников несколько — GrAvatarGroup собирает их в ряд с наложением и счётчиком.

Когда взять другое

НужноБерите
Изображение нужно рассмотретьGrImageViewer
Показывается иконка, а не человекGrIcon
Нужен счётчик поверх контролаGrBadgeWrap
Статус текстомGrBadge

Варианты все тона и виды — настоящим компонентом

Варианты · GrAvatar
status \ shapecirclesquare
online
offline
busy
away

Playground контролы выводятся из API, а не пишутся руками

Сцена

Загружается…

0 изменено· состояние — в адресе

Примеры 4 у каждого — живое демо и его код

  • Лицо у каждого события

    Фото, когда оно есть; без него name даёт инициалы и доступное имя, а auto-color — собственный цвет: у одного человека он одинаков во всём продукте, и ленту читают по пятнам раньше, чем по словам. Робот — не человек: слот по умолчанию получает его значок.

    Activity
    Ada Lin sent invoice INV-0418 to Northwind Traders9:41
    GW
    Grace Wu changed the due date of INV-0417 to 12 October9:12
    Billing robot charged Contoso Ltd €432.00 by card8:30
    Linus Ray added a note to Tailspin ToysYesterday
    MO
    Mina Ortiz invited [email protected] as an editorYesterday
  • Присутствие на лице

    status ставит отметку на аватар, потому что присутствие принадлежит человеку, а не строке: в списке из двадцати глаз находит, кто в сети, не читая. Точка декоративна — статус объявляется словом из локали, ведь цвет сам по себе смысла не несёт.

    Members1 online · 4 in the workspace
    ALв сети
    Ada LinOnline
    Owner
    GWзанят
    Grace WuIn a meeting until 11:00
    Admin
    LRотошёл
    Linus RayAway for 20 minutes
    Editor
    MOне в сети
    Mina OrtizLast seen 2 days ago
    Viewer
  • Команда в одном коротком ряду

    GrAvatarGroup накладывает лица друг на друга; max держит ряд коротким и сворачивает остальных в «+N», total считает тех, кого список не принёс. Группа названа, и диктор слышит «Invoice editor team, и ещё 3», а не шесть безымянных картинок; size доходит до каждого аватара внутри.

    Projects
    Invoice editorShips 20 Oct
    ALGWLR
    VAT reports for GermanyShips 4 Nov
    GWOH
    Mobile appShips in Q1
    SKLRAL
  • Компании квадратные, люди круглые

    shape с одного взгляда отличает пространство от человека. Логотип, чья ссылка больше не отвечает, откатывается по цепочке — src, потом fallback-src, потом инициалы из name — без значка сломанной картинки; alt называет изображение. :size="40" — выход для диаметра вне шкалы.

    Switch account

API порождается из пакета · разойтись не может

Props

PropTypeпо умолчаниюОписание
sizeGrSizeWithPx | undefinedundefinedРазмер по канонической шкале (`xs|sm|md|lg`) — тогда работает `GrConfigProvider`. Число — escape-hatch: аватар нужен произвольного диаметра (24px в строке списка, 96px в профиле), и четыре ступени шкалы этого не закрывают.
namestring | undefinedundefinedИмя участника: даёт инициалы и доступное имя аватара.
srcstring | undefinedundefinedАдрес фото. Пока грузится — скелет; не загрузился — `fallbackSrc`, затем инициалы.
fallbackSrcstring | undefinedundefinedРезервная картинка: показывается, когда `src` не загрузился.
altstring | undefinedundefinedДоступное имя аватара; сильнее `name`, когда подпись для диктора должна быть другой.
shapeGrAvatarShape | undefinedundefinedКруг или квадрат со скруглением. По умолчанию `circle`; группа задаёт форму всему ряду.
autoColorboolean | undefinedundefinedКрасить фон по имени: одинаковое имя всегда даёт одинаковый цвет. Выключен по умолчанию — серый аватар это осознанный нейтральный дефолт, а цветной может спорить с оформлением продукта. Палитру задаёт тема (`--gr-avatar-N-bg`/`-fg`), компонент только выбирает слот.
status"online" | "offline" | "busy" | "away" | undefinedundefinedСтатус участника. Точка декоративна — рядом идёт скрытая подпись.

Слоты

SlotTypeОписание
defaultanyСодержимое вместо картинки и инициалов.

Типы

Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.

Импорт
import type { GrAvatarGroupProps, GrAvatarProps, GrAvatarShape } from '@feugene/granularity/components/GrAvatar'

Файлdist/types/components/GrAvatar/GrAvatarGroup.vue.d.ts

GrAvatarGroupPropsinterface
interface GrAvatarGroupProps {
    /** Размер и форма ряда: дети берут их из контекста. */
    size?: GrSizeWithPx;
    shape?: GrAvatarShape;
    /** Сколько аватаров показывать; остальные сворачиваются в «+N». */
    max?: number;
    /** Сколько участников всего, если в слоте лежит лишь часть. */
    total?: number;
    /** Имя группы. Не задано — берётся из локали. */
    ariaLabel?: string;
}

Файлdist/types/components/GrAvatar/config.d.ts

grAvatarConfigconst
const grAvatarConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrAvatar">;

Файлdist/types/components/GrAvatar/GrAvatar.vue.d.ts

GrAvatarPropsinterface
interface GrAvatarProps {
    /**
     * Размер по канонической шкале (`xs|sm|md|lg`) — тогда работает
     * `GrConfigProvider`. Число — escape-hatch: аватар нужен произвольного
     * диаметра (24px в строке списка, 96px в профиле), и четыре ступени шкалы
     * этого не закрывают.
     */
    size?: GrSizeWithPx;
    /** Адрес фото. Пока грузится — скелет; не загрузился — `fallbackSrc`, затем инициалы. */
    src?: string;
    /** Резервная картинка: показывается, когда `src` не загрузился. */
    fallbackSrc?: string;
    /** Доступное имя аватара; сильнее `name`, когда подпись для диктора должна быть другой. */
    alt?: string;
    /** Имя участника: даёт инициалы и доступное имя аватара. */
    name?: string;
    /** Круг или квадрат со скруглением. По умолчанию `circle`; группа задаёт форму всему ряду. */
    shape?: GrAvatarShape;
    /**
     * Красить фон по имени: одинаковое имя всегда даёт одинаковый цвет.
     *
     * Выключен по умолчанию — серый аватар это осознанный нейтральный дефолт, а
     * цветной может спорить с оформлением продукта. Палитру задаёт тема
     * (`--gr-avatar-N-bg`/`-fg`), компонент только выбирает слот.
     */
    autoColor?: boolean;
    /** Статус участника. Точка декоративна — рядом идёт скрытая подпись. */
    status?: GrAvatarStatus;
}

Файлdist/types/components/GrAvatar/grAvatarStyles.d.ts

GrAvatarShapetype
type GrAvatarShape = 'circle' | 'square';
GrAvatarStatustype
type GrAvatarStatus = typeof GR_AVATAR_STATUSES[number];
initialsFromfunction

Инициалы из имени: первые буквы двух первых слов. Вынесено чистой функцией — тестируется без монтирования.

function initialsFrom(name: string): string;

Файлdist/types/components/GrAvatar/safelist.d.ts

grAvatarSafelistconst
const grAvatarSafelist: string[];

Файлdist/types/components/GrAvatar/defaults.d.ts

GrAvatarConfigurablePropsinterface

Пропы GrAvatar, настраиваемые глобально через <GrConfigProvider :component-defaults="{ GrAvatar: { … } }">. Только оформление — см. GrButton/defaults.ts.

interface GrAvatarConfigurableProps {
    size: GrComponentSize;
    shape: GrAvatarShape;
    autoColor: boolean;
}

Использование из прозы библиотеки

Что показывается

Порядок отката: src → fallbackSrc → инициалы из name → слот по умолчанию.

vue
<GrAvatar src="https://cdn.example/u/42.png" fallback-src="/avatar.svg" name="Ada Lovelace" />

Битая ссылка обрабатывается: по @error компонент переходит к следующему варианту, и браузер не рисует иконку сломанного изображения. Смена src сбрасывает ошибку — новая ссылка не наследует судьбу прошлой.

Пока картинка едет, её место держит скелет: иначе ряд аватаров мигает пустыми кружками.

Имя и инициалы

name даёт инициалы (первые буквы двух первых слов) и доступное имя. Когда есть картинка, имя несёт её alt; без картинки роль img и имя берёт на себя сам аватар — иначе кружок с инициалами для диктора пуст. alt сильнее name, слот сильнее инициалов.

Функция инициалов доступна отдельно: import { initialsFrom } from '@feugene/granularity'.

Кегль считается от диаметра — треть, но не меньше 10px. Размер аватара бывает произвольным числом пикселей, поэтому карта по ступеням шкалы его не закрывает. Правило одно на инициалы, слотовый текст и счётчик «+N» у GrAvatarGroup: они стоят в одном ряду, и разные пропорции читались бы как сбой.

Автоцвет по имени

autoColor красит фон по имени: одинаковое имя всегда даёт одинаковый цвет, поэтому человека в списке можно узнать по пятну ещё до чтения инициалов.

Выключен по умолчанию и включается на всё приложение через GrConfigProvider:

vue
<GrConfigProvider :component-defaults="{ GrAvatar: { autoColor: true } }">

Серый аватар — осознанный нейтральный дефолт: цветной кружок спорит с оформлением там, где аватар стоит внутри плотного интерфейса. Поэтому включение остаётся решением приложения, а не библиотеки.

Палитры внутри компонента нет. Шесть слотов (--gr-avatar-1-bg/-fg … -6-) объявлены в теме самого компонента (components/GrAvatar/themes/), и каждый по умолчанию ссылается на пару -light/-text готового тона — ту же, на которой стоит мягкий вариант GrBadge. Компонент считает только номер слота.

В глобальную тему палитра не идёт намеренно: она нужна одному компоненту, и там за неё платил бы и тот, кто GrAvatar не берёт. Тёмного файла у палитры нет — слот ссылается на роль, а роль переключается вместе с темой сама.

Приложению, которому не нужен пале-красный или пале-зелёный аватар, достаточно переопределить слот:

css
:root { --gr-avatar-4-bg: var(--gr-slate-light); --gr-avatar-4-fg: var(--gr-slate-text); }

Три тона из шести семантические, и это выбор, а не недосмотр: тона бледные, а в ряду людей цвет читается как идентичность, не как состояние. Ровно для несогласных существует переопределение выше.

Цвет виден только под инициалами: картинка закрывает фон целиком, а у пустого аватара красить нечего. Счётчик «+N» у GrAvatarGroup тоже остаётся нейтральным — это не участник, имени у него нет.

Контраст пары и различимость слотов держит гейт src/__tests__/avatarPalette.test.ts — в обеих темах сразу.

Статус
vue
<GrAvatar name="Ada Lovelace" status="online" />

online | offline | busy | away. Точка декоративна (aria-hidden), а статус объявляется словом из локали (gr.avatar.status.*): цвет сам по себе смысл не передаёт.

Ряд участников
vue
<GrAvatarGroup :max="3" :total="9" aria-label="Команда релиза">
  <GrAvatar v-for="member in team" :key="member.id" :name="member.name" />
</GrAvatarGroup>

max ограничивает число видимых аватаров, остаток сворачивается в «+N»; total нужен, когда в слоте лежит лишь часть участников. Группа объявлена role="group", а её имя содержит и подпись, и число скрытых — диктор слышит «Команда релиза, и ещё 6», а не набор безымянных картинок.

size и shape группы доходят до детей через контекст, чтобы ряд не расползался.

Размер и форма

size принимает ступень шкалы (xs…lg, читается из GrConfigProvider) или число пикселей — у аватара исторически произвольный диаметр. shape (circle | square) тоже настраивается глобально через componentDefaults.GrAvatar.shape.