Avatar & Badge
Two separate sets that spend most of their life in the same place: the leading slot of a List Row. The Avatar says who, the Badge says how many. Neither one positions the other; that is the consumer’s job.
Use when
Section titled “Use when”Use when
- Identifying a person or a number in a list, a header or a thread.
- Marking that something is unread or unseen, with a Dot.
- Counting something small and actionable, with a Count.
Don’t use when
- Labelling status or category with words. That is a Chip, and it does not exist yet.
- Showing a number that is information rather than a prompt. Use the trailing value slot of a List Row.
- Decorating. An avatar with no identity behind it is noise.
Avatar
Section titled “Avatar”40 × 40, radius/full, content clipped. One variant property, Content, with three values.
| Content | Background | Foreground | For |
|---|---|---|---|
| Photo | Neutral/200 placeholder | the image itself | anyone with a picture |
| Text | avatar/identity/1…6 | avatar/onIdentity, Inter Medium 14 / 20 | initials, or the last digits of an unknown number |
| Icon | scheme/surfaceContainerHighest | silhouette on text/secondary | system and non-human rows |
The identity colours mean nothing, on purpose
Section titled “The identity colours mean nothing, on purpose”The six avatar/identity stops are assigned deterministically from the contact id, never
from anything semantic. Two people get different colours so you can tell them apart at a
glance in a long list, and the same person keeps their colour forever. A colour never means
“VIP” or “blocked” or “unread”; the moment it does, the list stops being scannable.
All six are mode-independent: they hold the same value in Light, Carbon and Navy. That is deliberate. A contact whose avatar changed colour when you switched theme would stop being recognisable, which is the one job the colour has.
White initials clear 4.5:1 on every one of the six. The tightest is identity/3 at 6.13,
and the most generous is identity/2 at 14.66, so there is real headroom on all of them.
The indicator only. It does not know what it is attached to, exactly like Flutter’s native
Badge. Both variants fill with feedback/error and carry a 1.5 px stroke in
scheme/surface so they punch a hole in whatever they overlap rather than muddying into it.
| Content | Size | Label |
|---|---|---|
| Dot | 8 × 8 | none |
| Count | hugs, min 17 × 18, padding 1 / 5 | feedback/onError, Inter Medium 11 / 16 |
That stroke is the whole trick. Without it a red dot on a red-ish photo disappears; with it, the badge always has a surface-coloured ring separating it from its background, in every mode.
Red here is a counter, not an error. feedback/error owns four things: validation, the destructive confirm inside a dialog, negative amounts, and counter badges. An unread count is not a failure, it is just the one strong colour we allow for “look here”. See Colour as signage.
Design guidelines
Section titled “Design guidelines”One badge per avatar. A dot and a count on the same avatar is two answers to one question.
Counts cap at 99+. Past that the pill grows wider than the avatar it sits on, and the exact number stopped being useful a long time before.
The avatar is never the tap target on its own. In a list row the whole row is tappable. An avatar that opens a profile while the row opens a thread gives you two targets 40 px apart, which fails at the 360 dp floor.
Photo needs a fallback, always. Text is the fallback for people, Icon is the fallback for everything that is not a person. A broken image is never acceptable, because the avatar is often the only thing distinguishing two rows.
Tokens
Section titled “Tokens”The seven avatar/ tokens were added in July 2026 and are the newest group in the system. They
are also the only group where every token already carries a scope and a description, which is
the model the rest of the system is meant to follow.