# xpl-avatar

The **Avatar** component shows a person or entity: a photo, initials on a colored surface, or custom slot content. It aligns with Apollo’s Figma patterns for default avatars, profile layouts, stacked groups, and rows with supporting text.

## When to use

- **Default (no `variant`)** — Inline UI: tables, nav, comments, lists. Supports image (`src`), initials from `name`, and an optional status dot (`status`).
- **Profile (`variant="profile"`)** — Large avatars for profile pages and settings surfaces; optional `status` dot uses the same badge palette as the default avatar.
- **Group (`variant="group"`)** — Stacked avatar groups with overflow count (`+N`). The `status` prop is not used (status dots are not shown for groups).
- **With Text (`variant="with-text"`)** — Horizontal layout with avatar paired with name and optional sub-text; optional `status` on the avatar image.


| Variant     | Purpose                                                | `status` dot |
| ----------- | ------------------------------------------------------ | ------------ |
| *(none)*    | Standard single avatar                                 | Supported    |
| `profile`   | Larger profile-sized avatar for settings/profile pages | Supported    |
| `group`     | Stacked avatar group with overflow count (`+N`)        | Not shown    |
| `with-text` | Avatar paired with name and optional sub-text          | Supported    |


---

## Quick Start

### Basic Avatar (Image)

```html
<xpl-avatar name="Katie Wilson" src="https://example.com/photo.jpg"></xpl-avatar>
```

### Initials Placeholder (No Image)

```html
<!-- Automatic initials from name -->
<xpl-avatar name="Katie Wilson" color="green"></xpl-avatar>

<!-- Custom initials via slot -->
<xpl-avatar color="primary">KW</xpl-avatar>
```

### With Status Dot

Status dots are rendered with [`xpl-badge`] using `dot-only` and `bordered`. The `status` prop sets the badge **variant** , so avatar status colors stay aligned with badge semantics across the system.

**Where `status` applies:** default (no `variant`), `profile`, and `with-text`. It does **not** apply to `group` — stacked groups ignore `status`.

**`status` values** (same names as `xpl-badge` `variant` palette values):


| `status` | Badge palette    | Typical meaning (choose per product copy) |
| -------- | ---------------- | ----------------------------------------- |
| `purple` | Purple (default) | Default / general presence                |
| `green`  | Green            | Positive, available, success-aligned      |
| `yellow` | Yellow           | Caution, pending, away, warning-aligned   |
| `orange` | Orange           | Attention, busy, secondary emphasis       |
| `gray`   | Gray             | Neutral, offline, inactive                |
| `red`    | Red              | Error, do not disturb, critical           |
| `blue`   | Blue             | Informational, notifications              |


```html
<xpl-avatar name="Alex Chen" src="photo.jpg" status="green"></xpl-avatar>
<xpl-avatar name="Jordan Lee" status="red"></xpl-avatar>
<xpl-avatar name="Sam Smith" status="gray"></xpl-avatar>
<xpl-avatar variant="with-text" name="Riley Park" sub-text="Designer" src="photo.jpg" status="blue"></xpl-avatar>
```

### Clickable Avatar (Link)

```html
<xpl-avatar name="Profile" src="photo.jpg" href="/profile" target="_blank"></xpl-avatar>
```

---

## Variant Examples

### Profile Avatar (Larger Size)

For profile pages and settings surfaces. Optional `status` uses the same badge palette as other non-group variants.

```html
<!-- Large profile avatar (144px) -->
<xpl-avatar variant="profile" name="Katie Wilson" src="photo.jpg"></xpl-avatar>

<!-- With status dot -->
<xpl-avatar variant="profile" name="Katie Wilson" src="photo.jpg" status="green"></xpl-avatar>

<!-- Small profile avatar (80px) -->
<xpl-avatar variant="profile" name="Jordan Lee" size="sm"></xpl-avatar>
```

### Avatar Group (Stacked)

Displays up to 4 visible avatars with a `+N` overflow pill for additional members. The `status` prop is not used in this layout (no per-avatar or group-level status dot).

```html
<!-- Basic group with JSON data -->
<xpl-avatar
  variant="group"
  group-data='[
    {"name": "Alex", "color": "green"},
    {"name": "Jordan", "color": "yellow"},
    {"name": "Sam", "color": "pink"},
    {"src": "https://example.com/photo.jpg", "name": "Dana"},
    {"name": "Extra User"}
  ]'
></xpl-avatar>

<!-- Medium group -->
<xpl-avatar variant="group" size="md" group-data='[...]'></xpl-avatar>

<!-- Small group -->
<xpl-avatar variant="group" size="sm" group-data='[...]'></xpl-avatar>
```

**Group data format:**

```typescript
interface AvatarGroupItem {
  src?: string;     // Image URL (optional)
  name?: string;      // Used for initials and alt text
  color?: 'green' | 'yellow' | 'pink' | 'primary' | 'secondary';
}
```

### Avatar with Text

Horizontal layout with avatar + name + optional sub-text (e.g., email).

```html
<!-- Basic with-text -->
<xpl-avatar
  variant="with-text"
  name="Katie Wilson"
  sub-text="katie@example.com"
  src="photo.jpg"
></xpl-avatar>

<!-- Clickable version -->
<xpl-avatar
  variant="with-text"
  name="View Profile"
  sub-text="Product Designer"
  src="photo.jpg"
  href="/profile"
></xpl-avatar>

<!-- With status dot on the avatar -->
<xpl-avatar
  variant="with-text"
  name="Katie Wilson"
  sub-text="katie@example.com"
  src="photo.jpg"
  status="green"
></xpl-avatar>
```

---

## Size Options


| Size     | Default Avatar | Profile Avatar | Group              |
| -------- | -------------- | -------------- | ------------------ |
| *(none)* | 40×40px        | 144×144px      | 40×40px per avatar |
| `md`     | 32×32px        | —              | 32×32px per avatar |
| `sm`     | 24×24px        | 80×80px        | 24×24px per avatar |


---

## Status vs placeholder `color`

- **`status`** — Badge palette for the **status dot** (`purple` | `green` | `yellow` | `orange` | `gray` | `red` | `blue`). Passed through to `xpl-badge` as `variant`. Not used when `variant="group"`.
- **`color`** — Placeholder **surface** behind initials when there is no `src` (`green` | `yellow` | `pink` | `primary` | `secondary`). Unrelated to the status dot.

## Color Options (Placeholder Backgrounds)

Use `color` when no `src` is provided to set the placeholder background:

- `green` — Positive accent
- `yellow` — Highlight accent
- `pink` — Pink accent
- `primary` — Brand primary
- `secondary` — Action primary (purple)

---

## Design tokens

These are the main Apollo Foundation tokens used in `packages/apollo-core/src/css/avatar.css`. Use them when overriding or migrating styles.

| Role | Token(s) |
| ---- | -------- |
| Circular shape | `var(--xpl-border-radius-full)` |
| Placeholder surface (default) | `var(--xpl-background-brand-secondary)`, `var(--xpl-text-inverse)` |
| Placeholder `green` / `yellow` / `pink` | `var(--xpl-background-accent-positive)` / `var(--xpl-background-accent-highlight)` / `var(--xpl-background-accent-pink)` with `var(--xpl-text-inverse-on-light)` where applicable |
| Placeholder `primary` / `secondary` | `var(--xpl-background-accent-brand)` / `var(--xpl-background-brand-secondary)` |
| Link hover overlay | `var(--xpl-background-surface-transparent-25)` |
| Focus outline | `var(--xpl-border-accent-default)` base; `color` modifiers use `var(--xpl-border-positive)`, `var(--xpl-border-accent-highlight)`, `var(--xpl-border-accent-brand)`, etc. (`outline` / `outline-offset` per `avatar.css`) |
| With-text primary line | `var(--xpl-text-strong)`, `var(--xpl-font-size-title-5)`, `var(--xpl-font-weight-medium)` |
| With-text secondary line | `var(--xpl-text-subdued)`, `var(--xpl-font-size-body)` |
| Group overflow pill | `var(--xpl-background-surface-subtle)`, `var(--xpl-text-subdued)` |
| Group avatar ring | `box-shadow` using `var(--xpl-border-large)` and `var(--xpl-background-surface-default)` |
| Width / height | `var(--xpl-size-*)` for standard sizes; profile default uses `9rem` (documented in `TECH_DEBT.md`) |
| Spacing & overlap | `var(--xpl-space-*)`, `var(--xpl-z-index-*)` |

**Status dots** are styled by `xpl-badge`; see [`xpl-badge` readme](../xpl-badge/readme.md) for badge token usage.

---

## Accessibility

- `name` is required for proper `alt` text on images and screen reader announcements
- **Status dots** are implemented via `xpl-badge` and marked `aria-hidden` (purely visual); convey meaning in surrounding UI copy or labels if required
- **Group overflow** includes `aria-label="{count} more"` for screen readers
- **Links** use native `<a>` elements with full keyboard support
- **Disabled state**: Use `disabled` prop to disable link behavior while keeping visual styles
- **Focus management**: All interactive avatars (links) use `:focus-visible` for keyboard focus indicators

---

## Best Practices

1. **Always provide `name`** — Essential for accessibility (alt text and screen readers; for placeholder initials, slot input has higher priority than the value passed in `name`)
2. **Use `color` for placeholder consistency** — Assign consistent colors to users based on ID or name hash
3. **Limit group data** — While the component handles any number, consider capping at reasonable numbers for UX
4. **Slot content** — Use the default slot sparingly; prefer `name` prop for consistent initials generation

---

## Migration Notes

### Status Dot Implementation:

**What changed:** Status dots are implemented with `xpl-badge` (`dot-only` + `bordered`). The `status` prop uses the **badge color palette** (`purple`, `green`, `yellow`, `orange`, `gray`, `red`, `blue`) — the same names as `xpl-badge` `variant` — so avatar status stays consistent with badge semantics.

**Impact:**

- **Internal markup:** The status dot renders as `<xpl-badge dot-only bordered variant="...">` (with `variant` from `status`), not legacy `.xpl-avatar__dot--` classes.
- **CSS targeting:** Custom selectors like `.xpl-avatar__dot--active` / `--warning` / `--inactive` are not used. Target `.xpl-avatar .xpl-badge--dot-only` if you must override styles.
- **Prop values:** Use palette names above. Older examples sometimes used labels like `active` / `warning` / `inactive`; map those concepts to the palette (e.g. available → `green`, caution → `yellow`, offline → `gray`) per your design guidelines.

**Recommended migration:**

1. Replace custom CSS on `.xpl-avatar__dot--` with `.xpl-avatar .xpl-badge--dot-only` if needed
2. Set `status` to the badge palette value that matches the intended color (see the status table in this readme)
3. Remember `status` applies to default, `profile`, and `with-text` only — not `group`

### Legacy `status` values — scheduled for removal (next major release)

**These legacy string values are deprecated.** They exist only for backward compatibility with older integrations. They **will be removed** in the **next major** version of `@xplortech/apollo-core`. Plan your migration now; do not introduce new usage of the legacy names.

| Deprecated `status` | Current mapping (temporary) | Replace with (badge palette) |
| ------------------- | --------------------------- | ---------------------------- |
| `active`            | `green`                     | `green`                      |
| `inactive`          | `gray`                      | `gray`                       |
| `warning`           | `red`                       | `red`                        |

**Why:** Status dots use the same vocabulary as `xpl-badge` variants (`purple`, `green`, `yellow`, `orange`, `gray`, `red`, `blue`). The old semantic aliases (`active` / `warning` / `inactive`) duplicate that meaning with different names and increase maintenance cost, so they are being dropped from the public API.

**Action items before the major release:**

1. Search your codebase for `status="active"`, `status="inactive"`, and `status="warning"` on `<xpl-avatar>` (and framework wrappers).
2. Replace each with the **`green`**, **`gray`**, or **`red`** value from the table above, matching your product intent.
3. Re-test visuals: the mapped colors are unchanged today; after removal, only palette names will be accepted.

### Component Dependency

This component now depends on `xpl-badge`. Ensure `xpl-badge` is loaded in your application when using avatars with status dots.


<!-- Auto Generated Below -->


## Properties

| Property    | Attribute    | Description                                                                                                                                                                                                                                                                                                                                                           | Type                                                                                                              | Default     |
| ----------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------- |
| `color`     | `color`      | Background color when there is no image src                                                                                                                                                                                                                                                                                                                           | `"green" \| "pink" \| "primary" \| "secondary" \| "yellow"`                                                       | `undefined` |
| `disabled`  | `disabled`   | Sets a disabled state on the avatar when set to true                                                                                                                                                                                                                                                                                                                  | `boolean`                                                                                                         | `false`     |
| `groupData` | `group-data` | When `variant` is `group`, data for each face (max 4 visible + overflow count). Each item: { src?, name?, color? }.                                                                                                                                                                                                                                                   | `AvatarGroupItem[] \| string`                                                                                     | `undefined` |
| `href`      | `href`       | The URL if the avatar should be hyperlinked                                                                                                                                                                                                                                                                                                                           | `string`                                                                                                          | `undefined` |
| `name`      | `name`       | Alt text for the image; also used for initials when no image and no slot.                                                                                                                                                                                                                                                                                             | `string`                                                                                                          | `undefined` |
| `size`      | `size`       | Size of the avatar (and of each avatar in a group).                                                                                                                                                                                                                                                                                                                   | `"md" \| "sm"`                                                                                                    | `undefined` |
| `src`       | `src`        | The image URL                                                                                                                                                                                                                                                                                                                                                         | `string`                                                                                                          | `undefined` |
| `status`    | `status`     | <span style="color:red">**[DEPRECATED]**</span> :** `active`, `warning`, and `inactive` still map to `green`, `red`, and `gray` for existing consumers. Prefer palette names; legacy values are scheduled for removal in the next **major** release.<br/><br/>Shown for the default avatar, `profile`, and `with-text`; not shown when `variant` is `group`. **Legacy | `"active" \| "blue" \| "gray" \| "green" \| "inactive" \| "orange" \| "purple" \| "red" \| "warning" \| "yellow"` | `undefined` |
| `subText`   | `sub-text`   | Secondary text shown when `variant` is `with-text` (e.g. email).                                                                                                                                                                                                                                                                                                      | `string`                                                                                                          | `undefined` |
| `target`    | `target`     | Where to open the URL chosen for the `href` prop: `_self` (default), `_blank`, `_parent`, or `_top`                                                                                                                                                                                                                                                                   | `string`                                                                                                          | `undefined` |
| `variant`   | `variant`    | Optional layout: `profile` (large profile sizes), `group` (stacked faces + `groupData`; `status` not shown), `with-text` (avatar with `name` / `subText` beside it). Omit for the default single avatar.                                                                                                                                                              | `"group" \| "profile" \| "with-text"`                                                                             | `undefined` |


## Dependencies

### Used by

 - [xpl-list-item](../xpl-list/xpl-list-item)

### Depends on

- [xpl-badge](../xpl-badge)

### Graph
```mermaid
graph TD;
  xpl-avatar --> xpl-badge
  xpl-list-item --> xpl-avatar
  style xpl-avatar fill:#f9f,stroke:#333,stroke-width:4px
```

----------------------------------------------

*Built with [StencilJS](https://stenciljs.com/)*
