HabAvatar
Initials on a tint of a hue derived from the name.
<HabAvatar name="Ada Lovelace" />The color comes from the name
So the same person is the same color on every surface, with nothing stored. No preference to migrate, no column to add, no default to pick for a new user.
The hash is djb2 followed by an avalanche finalizer, and the finalizer is not decoration. The design source records an earlier accumulate-and-modulo version that gave one hue 25% of names and never picked another at all — mixing the high bits down is what makes % 8 see any entropy. habAvatarHue is exported so you can color something else by the same person — a chart series, a cursor — and have it match.
Eight ramp steps, not the full 65: most of the palette's lighten steps are indistinguishable from each other at 24px, and an avatar's whole job is to be told apart at a glance.
No photos
Deliberately. These are internal tools, and an avatar that can be a photo needs upload, cropping, a fallback and a broken-image state — four things to build and a fifth to get wrong.
Against HabIconTile
A tile says what kind of thing something is; an avatar says who. They share the 14% tint so a tile and an avatar for the same entity read as the same hue.
They differ in one measured way. A tile puts its glyph at the hue's full strength, which clears the 3:1 floor for a non-text object. Initials are text and need 4.5:1 — the source measured full-strength orange at 2.70 and lime at 2.24 on their own tints. So the initials are mixed toward --hab-hue-ink, which inverts per theme; a fixed dark ink measured 1.17 on dark surfaces.
Sizes
24 / 32 / 40, its own ladder — an avatar is not a control, so it does not sit on the 34px grid. The initials take the type ladder (11 / 12 / 13) rather than the source's off-ladder 10 / 12 / 14: a fourth and fifth font size existing only inside this component is worse than one pixel.
Accessibility
role="img"with the full name as the accessible name. The initials are not a name — a screen reader reading "AL" conveys nothing, and the design contract'stitleis a tooltip that browsers only sometimes also expose as a name.- Set
decorativewhen the name is written beside it, which is the common case in a list row or a table cell. Otherwise the name is announced twice. - An avatar with no name does not claim to be an image with an empty label.
API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
color | string | undefined | Override the derived hue. Any CSS color. |
decorative | boolean | false | Hides the avatar from assistive tech, for when the name is already written beside it. Two announcements of the same name is noise. |
initials | string | undefined | Override the derived initials. |
name | string | "" | Drives both the initials and the color, so the same person is the same color everywhere with nothing stored. |
size | "md" | "sm" | "lg" | "md" | — |