User avatar

The mark of our person — a CRM user — as opposed to a contact from outside. React packages/ui/src/components/UserAvatar.tsx, palette --uav-1..5 in apps/web/src/ds/entity-mark.css.

A colleague used to be drawn exactly like a contact: a circle, a hue from the name, initials. Meeting attendees are one list where colleagues and outside contacts are mixed, and the same ambiguity sat on the record owner, "reserved by", the author on the activity timeline and the sender in mail. A colleague now has a generated face; a contact keeps initials or a photo.

When to use

  • Wherever the record is a CRM user: owner, assignee, "reserved by", meeting attendee who is a colleague, timeline author, team lists, the account menu.
  • Through <EntityMark kind="user"> at a call site that handles mixed types — it delegates here.

When not to use

  • For a contact, however well known. The face means "this person has an account here"; putting it on a contact makes the one distinction it exists for meaningless.
  • As a decorative illustration or an empty-state graphic.

Anatomy

  • span.acrm-avatar.is-user.generated — the avatar box (circle, the same ladder: inline 16 · sm 24 · lg 32) with the ring and the ground removed, because the drawing fills the whole circle.
  • Inside, an inline SVG on a 36×36 canvas: a background, a face plane (circle or rounded square), eyes and a mouth. Position, rotation, scale, eye spread and mouth shape all come from one hash.
  • Palette: five vivid colours as tokens --uav-1..5, each with a paired -ink for the eyes and mouth. Deliberately not the entity tones --ic-* — seven muted UI tones would make colleagues look like siblings. Two different colours per face give 20 ordered pairs; with the shape variations, two colleagues practically never collide.
  • An uploaded photo (users.avatar_url) wins over the drawing and is cropped to the circle like any other avatar photo.
  • Determinism: the same hash that gives an avatar its hue, so the same person has the same face on every screen and nothing is stored — until someone regenerates.

Best practices

Do

  • Pass seed when the user has one stored; leave it empty otherwise, so a new colleague has a face immediately with nothing generated up front.
  • Keep the name next to the face; the face is recognition, not identification.

Don't

  • Derive the face from an e-mail, an id or anything else per screen — that would give one person two faces.
  • Draw the face for anyone who is not a user.
  • Add a ring or a badge around it. The drawing already differs from every other mark in the app.

Content

  • The face carries no meaning: it is a memory aid, not a status, a role or a mood.
  • Regenerating is a user's own choice in settings and stores users.avatar_seed. Without a stored seed the face follows the name, which is why the seed exists at all: a rename would otherwise silently change the face, and a regeneration would be undone by the next rename.
  • avatar — the contact's mark, initials or photo.
  • entity-mark — the type layer that routes user here.
  • Stories: components--user-avatar--default, --variants, --sizes, --states, --composition.

Source: docs/avatar/user-avatar.usage.md · GitLab