GrAvatar
Displays a user photo, or initials / a fallback when it is missing.
Overview
When to take it
- a person or an entity is recognised by a picture — a list of participants, the author of a comment, the owner of a task;
- there may be no picture — the fallback runs down a chain:
src,fallbackSrc, initials fromname, the slot; - a presence status is needed — a dot on the avatar instead of a separate marker beside it;
- there are several participants —
GrAvatarGroupcollects them into a row with overlap and a counter.
When to take something else
| Need | Take |
|---|---|
| The image has to be examined | GrImageViewer |
| An icon is shown, not a person | GrIcon |
| A counter on top of a control is needed | GrBadgeWrap |
| A status as text | GrBadge |
Variants every tone and view, rendered by the real component
status \ shape | circle | square |
|---|---|---|
online | ||
offline | ||
busy | ||
away |
Playground controls come from the API, not from hand
Loading…
0 changed· state is in the URL
<GrAvatar name="Alex Doe" />Examples 4 each with a live demo and its code
A face for every event
A photo when there is one; without it
namegives the initials and the accessible name, andauto-colora colour of its own — the same person keeps it across the product, so the feed is read by spots before words. A robot is not a person: the default slot takes its icon.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 editorYesterdayPresence on the face
statusputs the marker on the avatar, because presence belongs to the person, not to the row: in a list of twenty the eye finds who is online without reading. The dot is decorative — the status is announced in words from the locale, since colour alone carries no meaning.Members1 online · 4 in the workspaceALonlineAda LinOnlineOwnerGWbusyGrace WuIn a meeting until 11:00AdminLRawayLinus RayAway for 20 minutesEditorMOofflineMina OrtizLast seen 2 days agoViewerA team in one short row
GrAvatarGroupoverlaps the faces;maxkeeps the row short and folds the rest into «+N»,totalcounts the people the list did not bring. The group is named, so a screen reader hears «Invoice editor team, and 3 more» instead of six nameless pictures;sizereaches every avatar inside.ProjectsInvoice editorShips 20 OctALGWLRVAT reports for GermanyShips 4 NovGWOHMobile appShips in Q1SKLRALCompanies square, people round
shapetells a workspace from a person at a glance. A logo whose link no longer answers falls back along the chain —src, thenfallback-src, then initials fromname— without a broken-image icon;altnames the picture.:size="40"is the escape hatch for a diameter off the scale.Switch account
API generated from the package · cannot drift
Props
| Prop | Type | default | Description |
|---|---|---|---|
size | GrSizeWithPx | undefined | undefined | The size by the canonical scale (`xs|sm|md|lg`) — then `GrConfigProvider` applies. A number is an escape hatch: an avatar is needed at an arbitrary diameter (24px in a list row, 96px in a profile), and four steps of the scale do not cover that. |
name | string | undefined | undefined | The name of the participant: it gives the initials and the accessible name of the avatar. |
src | string | undefined | undefined | The address of the photo. While it loads — a skeleton; if it fails to load — `fallbackSrc`, then the initials. |
fallbackSrc | string | undefined | undefined | A fallback picture: shown when `src` did not load. |
alt | string | undefined | undefined | The accessible name of the avatar; stronger than `name` when the label for a screen reader must be different. |
shape | GrAvatarShape | undefined | undefined | A circle or a square with rounded corners. `circle` by default; a group sets the shape for the whole row. |
autoColor | boolean | undefined | undefined | Colour the background by the name: the same name always gives the same colour. Off by default — a grey avatar is a deliberate neutral default, while a coloured one can clash with the styling of the product. The palette is set by the theme (`--gr-avatar-N-bg`/`-fg`), the component only picks the slot. |
status | "online" | "offline" | "busy" | "away" | undefined | undefined | The status of the participant. The dot is decorative — a hidden label goes beside it. |
Slots
| Slot | Type | Description |
|---|---|---|
default | any | Content instead of the picture and the initials. |
Types
Every exported type of the subpath, grouped by the file it lives in. Names, generics and bodies come from the package’s declaration files and cannot drift.
import type { GrAvatarGroupProps, GrAvatarProps, GrAvatarShape } from '@feugene/granularity/components/GrAvatar'Filedist/types/components/GrAvatar/GrAvatarGroup.vue.d.ts
interface GrAvatarGroupProps {
size?: GrSizeWithPx;
shape?: GrAvatarShape;
max?: number;
total?: number;
ariaLabel?: string;
}Filedist/types/components/GrAvatar/config.d.ts
const grAvatarConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrAvatar">;Filedist/types/components/GrAvatar/GrAvatar.vue.d.ts
interface GrAvatarProps {
size?: GrSizeWithPx;
src?: string;
fallbackSrc?: string;
alt?: string;
name?: string;
shape?: GrAvatarShape;
autoColor?: boolean;
status?: GrAvatarStatus;
}Filedist/types/components/GrAvatar/grAvatarStyles.d.ts
type GrAvatarShape = 'circle' | 'square';type GrAvatarStatus = typeof GR_AVATAR_STATUSES[number];function initialsFrom(name: string): string;Filedist/types/components/GrAvatar/safelist.d.ts
const grAvatarSafelist: string[];Filedist/types/components/GrAvatar/defaults.d.ts
interface GrAvatarConfigurableProps {
size: GrComponentSize;
shape: GrAvatarShape;
autoColor: boolean;
}Usage from the library prose
What gets shown
The fallback order: src → fallbackSrc → initials from name → the default slot.
<GrAvatar src="https://cdn.example/u/42.png" fallback-src="/avatar.svg" name="Ada Lovelace" />A broken link is handled: on @error the component moves to the next option, and
the browser does not draw the broken-image icon. Changing src resets the error —
a new link does not inherit the fate of the previous one.
While the picture is on its way, its place is held by a skeleton: otherwise a row of avatars flickers with empty circles.
The name and the initials
name provides the initials (the first letters of the first two words) and the
accessible name. When there is a picture, the name serves as its alt; without a
picture the avatar itself takes the img role and the name — otherwise a circle
with initials is empty for a screen reader. alt beats name, the slot beats the
initials.
The initials function is available separately: import { initialsFrom } from '@feugene/granularity'.
The type size is computed from the diameter — a third of it, but no less than
10px. The size of an avatar can be an arbitrary number of pixels, so a map across
the steps of the scale does not cover it. The rule is one for the initials, the
slot text and the “+N” counter of GrAvatarGroup: they stand in the same row, and
different proportions would read as a defect.
Auto colour by name
autoColor colours the background by the name: the same name always gives the
same colour, so a person in a list can be recognised by the patch before the
initials are read.
It is off by default and is switched on for the whole application through
GrConfigProvider:
<GrConfigProvider :component-defaults="{ GrAvatar: { autoColor: true } }">A grey avatar is a deliberate neutral default: a coloured circle argues with the design where an avatar stands inside a dense interface. Switching it on therefore remains a decision of the application rather than of the library.
There is no palette inside the component. The six slots (--gr-avatar-1-bg/-fg …
-6-) are declared in the theme of the component itself (components/GrAvatar/themes/),
and each by default refers to the -light/-text pair of a ready tone — the
same one the soft variant of GrBadge stands on. The component computes only
the number of the slot.
The palette deliberately does not go into the global theme: one component needs
it, and there it would be paid for by whoever does not take GrAvatar as well.
The palette has no dark file — a slot refers to a role, and the role switches
together with the theme on its own.
An application that has no need of a pale red or a pale green avatar only has to override the slot:
:root { --gr-avatar-4-bg: var(--gr-slate-light); --gr-avatar-4-fg: var(--gr-slate-text); }Three of the six tones are semantic, and that is a choice rather than an oversight: the tones are pale, and in a row of people colour reads as identity rather than as a state. The override above exists precisely for those who disagree.
The colour is visible only under the initials: a picture covers the background
entirely, and an empty avatar has nothing to colour. The “+N” counter of
GrAvatarGroup stays neutral as well — it is not a participant, it has no name.
The contrast of a pair and the distinguishability of the slots are held by the
src/__tests__/avatarPalette.test.ts gate — in both themes at once.
The status
<GrAvatar name="Ada Lovelace" status="online" />online | offline | busy | away. The dot is decorative (aria-hidden), and the
status is announced with a word from the locale (gr.avatar.status.*): colour on
its own carries no meaning.
A row of participants
<GrAvatarGroup :max="3" :total="9" aria-label="Release team">
<GrAvatar v-for="member in team" :key="member.id" :name="member.name" />
</GrAvatarGroup>max limits the number of visible avatars, the remainder collapses into “+N”;
total is needed when the slot holds only part of the participants. The group is
declared role="group", and its name contains both the label and the number
hidden — a screen reader says “Release team, and 6 more” rather than a set of
nameless pictures.
The size and shape of the group reach the children through context, so the row
does not fall apart.
Size and shape
size accepts a step of the scale (xs…lg, read from GrConfigProvider) or a
number of pixels — an avatar has historically had an arbitrary diameter. shape
(circle | square) is likewise configured globally through
componentDefaults.GrAvatar.shape.
Props in this example