# `PhiaUi.Components.Avatar`
[🔗](https://github.com/charlenopires/PhiaUI/blob/v0.1.17/lib/phia_ui/components/display/avatar.ex#L1)

Circular user avatar with automatic image-fallback to initials.

Follows the shadcn/ui Avatar anatomy: a composable set of sub-components
that work together to display a profile image with a graceful fallback.
The fallback mechanism is powered by an inline `onerror` attribute on the
`<img>` tag — no JavaScript hook is required.

## Sub-components

| Component         | Element  | Purpose                                                  |
|-------------------|----------|----------------------------------------------------------|
| `avatar/1`        | `<span>` | Circular clipping container with configurable size       |
| `avatar_image/1`  | `<img>`  | Profile image; hides itself and reveals fallback on error|
| `avatar_fallback/1`| `<span>`| Initials or custom content shown when image is absent    |
| `avatar_group/1`  | `<div>`  | Overlapping stack of avatars with negative margin        |

## Sizes

| Value       | Dimensions       | Tailwind classes |
|-------------|------------------|-----------------|
| `"sm"`      | 24 × 24 px       | `h-6 w-6`       |
| `"default"` | 40 × 40 px       | `h-10 w-10`     |
| `"lg"`      | 56 × 56 px       | `h-14 w-14`     |
| `"xl"`      | 72 × 72 px       | `h-18 w-18`     |

## Image with automatic fallback

The most common pattern. When the image URL is valid, the photo is shown.
When the image fails to load (broken URL, network error, 404), the
`onerror` handler hides the `<img>` and reveals `avatar_fallback/1`:

    <.avatar>
      <.avatar_image src={@user.avatar_url} alt={@user.name} />
      <.avatar_fallback name={@user.name} />
    </.avatar>

## Fallback only (no image available)

When you know ahead of time that there is no image — for example when the
user has not uploaded one yet — omit `avatar_image/1`:

    <.avatar size="lg">
      <.avatar_fallback name="Jane Smith" />
    </.avatar>

## Icon placeholder

Supply a custom inner block to `avatar_fallback/1` instead of using the
`:name` prop:

    <.avatar>
      <.avatar_fallback>
        <.icon name="user" size={:xs} />
      </.avatar_fallback>
    </.avatar>

## Team member list with AvatarGroup

Use `avatar_group/1` to render an overlapping cluster of avatars, common
in "assigned to" or "members" widgets. Apply `ring-2 ring-background` to
individual avatars to create a visible separation between overlapping items:

    <%!-- Shows up to 4 avatars then a +N overflow badge --%>
    <div class="flex items-center gap-2">
      <.avatar_group>
        <%= for member <- Enum.take(@team.members, 4) do %>
          <.avatar class="ring-2 ring-background" size="sm">
            <.avatar_image src={member.avatar_url} alt={member.name} />
            <.avatar_fallback name={member.name} />
          </.avatar>
        <% end %>
      </.avatar_group>
      <%= if length(@team.members) > 4 do %>
        <span class="text-sm text-muted-foreground">
          +{length(@team.members) - 4} more
        </span>
      <% end %>
    </div>

## Comment thread with avatars

    <%= for comment <- @comments do %>
      <div class="flex gap-3">
        <.avatar size="sm">
          <.avatar_image src={comment.author.avatar_url} alt={comment.author.name} />
          <.avatar_fallback name={comment.author.name} />
        </.avatar>
        <div>
          <p class="text-sm font-medium">{comment.author.name}</p>
          <p class="text-sm text-muted-foreground">{comment.body}</p>
        </div>
      </div>
    <% end %>

## How the onerror fallback works

The `avatar_image/1` component attaches an inline `onerror` JavaScript
handler directly to the `<img>` element:

    onerror="this.style.display='none';
             var fb=this.parentElement.querySelector('[data-avatar-fallback]');
             if(fb)fb.style.display='flex';"

When the browser fails to load the image source it fires the `onerror`
event synchronously. The handler:
1. Hides the `<img>` (`display: none`).
2. Queries the parent for a `[data-avatar-fallback]` sibling.
3. Reveals it by setting `display: flex`.

`avatar_fallback/1` carries `data-avatar-fallback` to serve as the target.
This keeps the mechanism entirely CSS/HTML — no Phoenix hook needed.

# `avatar`

Renders a circular avatar container.

The container is a `<span>` with `overflow-hidden rounded-full` so any
child — whether an image or initials fallback — is always clipped to a
perfect circle regardless of the source aspect ratio.

## Example

    <.avatar size="lg">
      <.avatar_image src="/avatars/jane.jpg" alt="Jane Smith" />
      <.avatar_fallback name="Jane Smith" />
    </.avatar>

## Attributes

* `size` (`:string`) - Avatar size. One of `"sm"` (24px), `"default"` (40px), `"lg"` (56px), `"xl"` (72px). Defaults to `"default"`. Must be one of `"sm"`, `"default"`, `"lg"`, or `"xl"`.
* `label` (`:string`) - Accessible label (aria-label). Use for standalone avatars that convey meaning. Defaults to `nil`.
* `class` (`:string`) - Additional CSS classes merged via `cn/1`. Useful for adding `ring-2 ring-background` in avatar groups. Defaults to `nil`.
* Global attributes are accepted. HTML attributes forwarded to the root `<span>` element.
## Slots

* `inner_block` (required) - `avatar_image/1` and/or `avatar_fallback/1` sub-components.

# `avatar_fallback`

Renders the avatar fallback displayed when no image is available or loading fails.

There are two ways to supply content:

1. **`:name` attribute** — pass the user's full name; up to two initials
   are extracted and uppercased automatically (`"Jane Smith"` → `"JS"`).

2. **Inner block** — provide any content (e.g. an icon). When an inner
   block is present, `:name` is ignored.

The element carries `data-avatar-fallback` so that `avatar_image/1`'s
`onerror` handler can locate and reveal it after an image load failure.

## Examples

    <%!-- Auto initials --%>
    <.avatar_fallback name="Carlos Mendoza" />

    <%!-- Custom icon --%>
    <.avatar_fallback>
      <.icon name="user" size={:xs} />
    </.avatar_fallback>

## Attributes

* `name` (`:string`) - Full name from which up to two initials are derived. `"Jane Smith"` → `"JS"`, `"Alice"` → `"A"`. Ignored when an inner block is provided. Defaults to `nil`.
* `class` (`:string`) - Additional CSS classes merged via `cn/1`. Defaults to `nil`.
* Global attributes are accepted. HTML attributes forwarded to the root `<span>` element.
## Slots

* `inner_block` - Custom fallback content. When provided, overrides the `:name` initials. Useful for icon placeholders.

# `avatar_image`

Renders the avatar image with an automatic fallback on load error.

When the image loads successfully, it fills the avatar container using
`object-cover` to maintain the circular crop without distortion.

When the image **fails** to load (broken URL, 404, network error), the
inline `onerror` handler:
1. Hides this `<img>` element.
2. Finds and reveals the sibling `avatar_fallback/1` (identified by
   `data-avatar-fallback`).

This happens synchronously in the browser — no LiveView round-trip needed.

## Example

    <.avatar_image src={@user.photo_url} alt={@user.name} loading="lazy" />

## Attributes

* `src` (`:string`) (required) - The image URL. When the URL fails to load, the `avatar_fallback/1` sibling is revealed automatically.
* `alt` (`:string`) - Accessible alt text. Use the user's full name for proper screen reader support. Defaults to `""`.
* `class` (`:string`) - Additional CSS classes merged via `cn/1`. Defaults to `nil`.
* Global attributes are accepted. HTML attributes forwarded to the `<img>` element (e.g. `loading="lazy"`).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
