A circular display element showing user initials or a profile image. Supports 7 sizes (20px-90px) and 3 types (dark initials, light initials, image). Used when a profile image is unavailable or for visual user identification.
main/avatar/brand/initials, variant names are verified, and every initials variant is drawn with vector shapes.How the avatar appears in a real product screen — Contacts list with Favorites row (brand fill + default fill avatars in circular display).
main/avatar/...). Variant naming verified correct (type=initials-light). Border-radius tokenized to radius/radius-round. The initials token reads main/avatar/brand/initials.| State | iOS | Android | Figma Property | Notes |
|---|---|---|---|---|
| Default | Yes | Yes | type + size | Display-only. All 3 types fully defined across 7 sizes. |
| Pressed | N/A | N/A | -- | Display-only component. Tap behavior handled by parent container. |
| Disabled | N/A | N/A | -- | Display-only component. No disabled state. |
| Focused (a11y) | N/A | N/A | -- | Display-only. Focus rings rendered by parent interactive container if needed. |
- Border-radius: bound to
radius/radius-round(99999) across all sizes — previously hardcoded per size (C3) - Border-width: confirmed fixed per size by design — not a token gap (C3)
- Raster backgrounds replaced with vector ELLIPSE layers across all 5 affected initials variants (C6)
- Avatar Group compound component created (previously a design recommendation) — see sibling component under Avatar group (C2)
- Variant property value naming verified on recheck: variant names are correctly hyphenated as
type=initials-lightin Figma source. Earlier "spaces" report was an MCP output artifact (TypeScript enum generation converts hyphens to spaces). No action required. C2 Verified
- Add a status
badgeoverlay slot. Common in chat, contacts, and profile lists — online/offline dots, notification counts, verified checkmarks. Today consumers stack a Badge manually on top of Avatar; a built-in slot encodes the correct offset and sizing. Slot
Component Playground
Layout
VStack
Typography
Colors
iOS — Swift Package Manager
.package(url: "https://github.com/AY-Org/eb-ds-ios", from: "1.0.0")
Android — Gradle (Kotlin DSL)
implementation("com.eastblue.ds:avatar:1.0.0")
Import
import EastBlueDS import com.eastblue.ds.avatar.*
Every row maps a Figma component property to its native equivalent.
| Figma Property | SwiftUI | Compose |
|---|---|---|
| type — dark-initials, image, initials-light | .darkInitials / .image(url:) / .lightInitials | AvatarType.DarkInitials / Image(url) / LightInitials |
| size — 90px, 64px, 48px, 40px, 32px, 24px, 20px | size: AvatarSize | size: AvatarSize |
// Dark initials
EBAvatar("DM", type: .darkInitials, size: .large) // Dark initials
EBAvatar(
initials = "DM",
type = AvatarType.DarkInitials,
size = AvatarSize.Large
) // Light initials
EBAvatar("LM", type: .lightInitials, size: .medium) // Light initials
EBAvatar(
initials = "LM",
type = AvatarType.LightInitials,
size = AvatarSize.Medium
) // Image
EBAvatar(imageURL: profileURL, size: .large) // Image
EBAvatar(
imageUrl = profileUrl,
type = AvatarType.Image,
size = AvatarSize.Large
) | Requirement | iOS | Android |
|---|---|---|
| Alt text | accessibilityLabel("User avatar") | contentDescription = "User avatar" |
| Decorative mode | isAccessibilityElement = false (in lists) | importantForAccessibility = no |
| Image loading | AsyncImage with placeholder | SubcomposeAsyncImage with placeholder |
Do
Use dark-initials as default when no photo is available.
Don't
Use image type with placeholder -- use initials instead.
Do
Match avatar size to context (20px in dense lists, 90px in profiles).
Don't
Mix initials types in the same context.
Do
Always pass 2-letter initials (first + last).
Don't
Show single-letter or empty initials.
Do
Provide alt text for image avatars.
Don't
Skip accessibility labels.
| ID | Criterion | Status | Notes |
|---|---|---|---|
| C1 | Layer Structure & Naming | Ready | Layers named container, background, replace here - image. Simple hierarchy. Minor: some sizes have a child also named container. |
| C2 | Variant & Property Naming | Ready | Variant naming resolved (initials-light). Token name typo fixed (main/avatar/brand/initials). Size values use px suffix (minor, no impact on native mapping). |
| C3 | Token Coverage | Needs Refinement | 8 color tokens, full typography tokens, and radius/radius-round connected. Border-width is fixed per size (by design). |
| C4 | Native Mappability | Ready | Maps to custom Circle-clipped view on both platforms. No web-only patterns. |
| C5 | Interaction State Coverage | Not Applicable | Display-only component. No interactive states needed. |
| C6 | Asset & Icon Quality | Ready | All initials variants now use vector ELLIPSE layers. Image type rasters are expected (user photos). |
3 type × 7 size = 21 variants. No interaction state axis (display-only component).
| Type | Sizes | Notes | Count |
|---|---|---|---|
| dark-initials | 20, 24, 32, 40, 48, 64, 90 px | Brand background, white initials | 7 |
| initials-light | 20, 24, 32, 40, 48, 64, 90 px | Light background, dark initials | 7 |
| image | 20, 24, 32, 40, 48, 64, 90 px | Photo fill (raster expected) | 7 |
View full type × size breakdown (21 rows)
| type | size | Node |
|---|---|---|
| dark-initials | 20px | 17143:4489 |
| initials-light | 20px | 17143:4492 |
| image | 20px | 17143:4495 |
| dark-initials | 24px | 17143:4497 |
| initials-light | 24px | 17143:4500 |
| image | 24px | 17143:4503 |
| dark-initials | 32px | 17143:4505 |
| initials-light | 32px | 17143:4508 |
| image | 32px | 17143:4511 |
| dark-initials | 40px | 17143:4513 |
| initials-light | 40px | 17143:4517 |
| image | 40px | 17143:4521 |
| dark-initials | 48px | 17143:4523 |
| initials-light | 48px | 17143:4526 |
| image | 48px | 17143:4529 |
| dark-initials | 64px | 17143:4531 |
| initials-light | 64px | 17143:4535 |
| dark-initials | 90px | 17143:4539 |
| initials-light | 90px | 17143:4542 |
| image | 64px | 17143:4546 |
| image | 90px | 17143:4548 |
type=initials - light renamed to type=initials-light across all 7 variants. Now matches dark-initials hyphen style.
Fixedmain/avatar/brand/intials corrected to main/avatar/brand/initials. Token now maps correctly to native implementations.
Fixedradius/radius-round (99999) instead of hardcoded per-size values (45.213px, 24px, 16px, 12px, 10px).
Fixed