GrAvatar
Берут, когда человека или сущность узнают по картинке.
Обзор
Когда брать
- человека или сущность узнают по картинке — список участников, автор комментария, владелец задачи;
- картинки может не быть — откат идёт по цепочке:
src,fallbackSrc, инициалы изname, слот; - нужен статус присутствия — точка на аватаре вместо отдельного значка рядом;
- участников несколько —
GrAvatarGroupсобирает их в ряд с наложением и счётчиком.
Когда взять другое
| Нужно | Берите |
|---|---|
| Изображение нужно рассмотреть | GrImageViewer |
| Показывается иконка, а не человек | GrIcon |
| Нужен счётчик поверх контрола | GrBadgeWrap |
| Статус текстом | GrBadge |
Варианты все тона и виды — настоящим компонентом
status \ shape | circle | square |
|---|---|---|
online | ||
offline | ||
busy | ||
away |
Playground контролы выводятся из API, а не пишутся руками
Загружается…
0 изменено· состояние — в адресе
<GrAvatar name="Alex Doe" />Примеры 4 у каждого — живое демо и его код
Лицо у каждого события
Фото, когда оно есть; без него
nameдаёт инициалы и доступное имя, аauto-color— собственный цвет: у одного человека он одинаков во всём продукте, и ленту читают по пятнам раньше, чем по словам. Робот — не человек: слот по умолчанию получает его значок.ActivityAda Lin sent invoice INV-0418 to Northwind Traders9:41GWGrace Wu changed the due date of INV-0417 to 12 October9:12Billing robot charged Contoso Ltd €432.00 by card8:30Linus Ray added a note to Tailspin ToysYesterdayMOMina Ortiz invited [email protected] as an editorYesterdayПрисутствие на лице
statusставит отметку на аватар, потому что присутствие принадлежит человеку, а не строке: в списке из двадцати глаз находит, кто в сети, не читая. Точка декоративна — статус объявляется словом из локали, ведь цвет сам по себе смысла не несёт.Members1 online · 4 in the workspaceALв сетиAda LinOnlineOwnerGWзанятGrace WuIn a meeting until 11:00AdminLRотошёлLinus RayAway for 20 minutesEditorMOне в сетиMina OrtizLast seen 2 days agoViewerКоманда в одном коротком ряду
GrAvatarGroupнакладывает лица друг на друга;maxдержит ряд коротким и сворачивает остальных в «+N»,totalсчитает тех, кого список не принёс. Группа названа, и диктор слышит «Invoice editor team, и ещё 3», а не шесть безымянных картинок;sizeдоходит до каждого аватара внутри.ProjectsInvoice editorShips 20 OctALGWLRVAT reports for GermanyShips 4 NovGWOHMobile appShips in Q1SKLRALКомпании квадратные, люди круглые
shapeс одного взгляда отличает пространство от человека. Логотип, чья ссылка больше не отвечает, откатывается по цепочке —src, потомfallback-src, потом инициалы изname— без значка сломанной картинки;altназывает изображение.:size="40"— выход для диаметра вне шкалы.Switch account
API порождается из пакета · разойтись не может
Props
| Prop | Type | по умолчанию | Описание |
|---|---|---|---|
size | GrSizeWithPx | undefined | undefined | Размер по канонической шкале (`xs|sm|md|lg`) — тогда работает `GrConfigProvider`. Число — escape-hatch: аватар нужен произвольного диаметра (24px в строке списка, 96px в профиле), и четыре ступени шкалы этого не закрывают. |
name | string | undefined | undefined | Имя участника: даёт инициалы и доступное имя аватара. |
src | string | undefined | undefined | Адрес фото. Пока грузится — скелет; не загрузился — `fallbackSrc`, затем инициалы. |
fallbackSrc | string | undefined | undefined | Резервная картинка: показывается, когда `src` не загрузился. |
alt | string | undefined | undefined | Доступное имя аватара; сильнее `name`, когда подпись для диктора должна быть другой. |
shape | GrAvatarShape | undefined | undefined | Круг или квадрат со скруглением. По умолчанию `circle`; группа задаёт форму всему ряду. |
autoColor | boolean | undefined | undefined | Красить фон по имени: одинаковое имя всегда даёт одинаковый цвет. Выключен по умолчанию — серый аватар это осознанный нейтральный дефолт, а цветной может спорить с оформлением продукта. Палитру задаёт тема (`--gr-avatar-N-bg`/`-fg`), компонент только выбирает слот. |
status | "online" | "offline" | "busy" | "away" | undefined | undefined | Статус участника. Точка декоративна — рядом идёт скрытая подпись. |
Слоты
| Slot | Type | Описание |
|---|---|---|
default | any | Содержимое вместо картинки и инициалов. |
Типы
Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.
import type { GrAvatarGroupProps, GrAvatarProps, GrAvatarShape } from '@feugene/granularity/components/GrAvatar'Файлdist/types/components/GrAvatar/GrAvatarGroup.vue.d.ts
interface GrAvatarGroupProps {
/** Размер и форма ряда: дети берут их из контекста. */
size?: GrSizeWithPx;
shape?: GrAvatarShape;
/** Сколько аватаров показывать; остальные сворачиваются в «+N». */
max?: number;
/** Сколько участников всего, если в слоте лежит лишь часть. */
total?: number;
/** Имя группы. Не задано — берётся из локали. */
ariaLabel?: string;
}Файлdist/types/components/GrAvatar/config.d.ts
const grAvatarConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrAvatar">;Файлdist/types/components/GrAvatar/GrAvatar.vue.d.ts
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
type GrAvatarShape = 'circle' | 'square';type GrAvatarStatus = typeof GR_AVATAR_STATUSES[number];Инициалы из имени: первые буквы двух первых слов. Вынесено чистой функцией — тестируется без монтирования.
function initialsFrom(name: string): string;Файлdist/types/components/GrAvatar/safelist.d.ts
const grAvatarSafelist: string[];Файлdist/types/components/GrAvatar/defaults.d.ts
Пропы GrAvatar, настраиваемые глобально через
<GrConfigProvider :component-defaults="{ GrAvatar: { … } }">.
Только оформление — см. GrButton/defaults.ts.
interface GrAvatarConfigurableProps {
size: GrComponentSize;
shape: GrAvatarShape;
autoColor: boolean;
}Использование из прозы библиотеки
Что показывается
Порядок отката: src → fallbackSrc → инициалы из name → слот по умолчанию.
<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:
<GrConfigProvider :component-defaults="{ GrAvatar: { autoColor: true } }">Серый аватар — осознанный нейтральный дефолт: цветной кружок спорит с оформлением там, где аватар стоит внутри плотного интерфейса. Поэтому включение остаётся решением приложения, а не библиотеки.
Палитры внутри компонента нет. Шесть слотов (--gr-avatar-1-bg/-fg …
-6-) объявлены в теме самого компонента (components/GrAvatar/themes/),
и каждый по умолчанию ссылается на пару -light/-text готового тона — ту же,
на которой стоит мягкий вариант GrBadge. Компонент считает только номер слота.
В глобальную тему палитра не идёт намеренно: она нужна одному компоненту, и
там за неё платил бы и тот, кто GrAvatar не берёт. Тёмного файла у палитры
нет — слот ссылается на роль, а роль переключается вместе с темой сама.
Приложению, которому не нужен пале-красный или пале-зелёный аватар, достаточно переопределить слот:
:root { --gr-avatar-4-bg: var(--gr-slate-light); --gr-avatar-4-fg: var(--gr-slate-text); }Три тона из шести семантические, и это выбор, а не недосмотр: тона бледные, а в ряду людей цвет читается как идентичность, не как состояние. Ровно для несогласных существует переопределение выше.
Цвет виден только под инициалами: картинка закрывает фон целиком, а у пустого
аватара красить нечего. Счётчик «+N» у GrAvatarGroup тоже остаётся
нейтральным — это не участник, имени у него нет.
Контраст пары и различимость слотов держит гейт
src/__tests__/avatarPalette.test.ts — в обеих темах сразу.
Статус
<GrAvatar name="Ada Lovelace" status="online" />online | offline | busy | away. Точка декоративна (aria-hidden), а статус
объявляется словом из локали (gr.avatar.status.*): цвет сам по себе смысл не
передаёт.
Ряд участников
<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.
Пропы этого примера