Corex.Avatar
(Corex v0.1.0-beta.2)
View Source
Phoenix implementation of Zag.js Avatar.
Examples
Basic
<.avatar id="avatar" src="/me.jpg" class="avatar">
<:fallback>JD</:fallback>
</.avatar>Custom fallback with :let (:value slot)
Same idea as the angle slider value_text slot: override the fallback body and receive the current src as value.
<.avatar id="avatar" src="/me.jpg" class="avatar">
<:value :let={value}>{if value, do: "JD", else: "?"}</:value>
</.avatar>When the :value slot is omitted, <:fallback> is used.
pending vs the hooked avatar
With pending={true}, the component does not mount phx-hook="Avatar", does not run Zag, and does not render an <img>.
Assigns such as src have no visible effect until you re-render with pending={false}.
The :loading slot is only used in that pending branch (custom markup or avatar_skeleton/1 when empty); it is not a replacement for the hooked avatar’s own loading UI.
Async loading
<.async_result :let={profile} assign={@profile}>
<:loading>
<.avatar_skeleton class="avatar" />
</:loading>
<:failed>Could not load.</:failed>
<.avatar id="user-avatar" src={profile.avatar_url} class="avatar">
<:fallback>{profile.initials}</:fallback>
</.avatar>
</.async_result>Pending without async_result
<.avatar pending class="avatar">
<:loading><span class="text-sm">Loading…</span></:loading>
</.avatar>When pending is true and the :loading slot is empty, avatar_skeleton/1 is used.
API
The API targets one avatar via its DOM id (the same id you pass to avatar/1).
For loaded, use respond_to: :server | :client | :both to control whether the response is pushed to LiveView, dispatched as a DOM event, or both.
<.action phx-click={Corex.Avatar.set_src("my-avatar", "https://example.com/a.png")}>Set image</.action>
<.action phx-click={Corex.Avatar.loaded("my-avatar")}>Read loaded</.action>Events
User interaction and imperative API use different channels. See also on_status_change / on_status_change_client on avatar/1.
User interaction
When phx-hook="Avatar" is active, Zag invokes on_status_change (server) and on_status_change_client (client CustomEvent type you set). Params / event.detail include %{"id" => dom_id, "status" => "loaded" | "error"} (string keys from the server; camelCase in JS detail as emitted by the hook).
Imperative API (LiveView helpers and client DOM)
From LiveView, use Corex.Avatar.set_src/3 and loaded/3. They use push_event/3 to the hook; optional respond_to controls where the answer goes for loaded/3.
From the client, dispatch CustomEvents on the hook root (e.g. #my-avatar):
| Dispatch (type) | detail |
|---|---|
corex:avatar:set-src | src — image URL string |
corex:avatar:loaded | optional respond_to: "server", "client", or "both" |
Responses to LiveView (push_event from the hook; handle in handle_event/3):
avatar_loaded_response—%{"id" => ..., "loaded" => boolean}
Responses to the DOM (listen on the hook root element):
avatar-loaded—detailwithidandloaded
Styling
Use data attributes to target elements:
[data-scope="avatar"][data-part="root"] {}
[data-scope="avatar"][data-part="image"] {}
[data-scope="avatar"][data-part="fallback"] {}
[data-scope="avatar"][data-part="skeleton"] {}If you wish to use the default Corex styling, you can use the class avatar on the component.
This requires to install Mix.Tasks.Corex.Design first and import the component css file.
@import "../corex/main.css";
@import "../corex/tokens/themes/neo/light.css";
@import "../corex/components/avatar.css";You can then use modifiers
<.avatar class="avatar avatar--accent avatar--lg">
<:fallback>JD</:fallback>
</.avatar>
Summary
Components
Static loading placeholder for use with <.async_result> or when pending is true without a :loading slot.
API
Requests whether the avatar image is loaded from the browser. Returns a Phoenix.LiveView.JS command.
Requests loaded state from the client. Pushes a LiveView event handled by the hook.
Sets the avatar image URL from the client. Returns a Phoenix.LiveView.JS command.
Sets the avatar image URL from the server. Pushes a LiveView event handled by the hook.
Components
Attributes
id(:string) - The id of the avatar.src(:string) - Image source URL. Defaults tonil.alt(:string) - Alternative text for the image. Defaults to"".dir(:string) - Direction. Defaults tonil. Must be one ofnil,"ltr", or"rtl".pending(:boolean) - When true, renders only the loading UI (:loadingslot oravatar_skeleton/1), without the Avatar hook. Defaults tofalse.on_status_change(:string) - Server event when image load status changes. Defaults tonil.on_status_change_client(:string) - Client event when image load status changes. Defaults tonil.- Global attributes are accepted.
Slots
loading- Custom loading content whenpendingis true. Overrides defaultavatar_skeleton/1. Accepts attributes:class(:string)
fallback- Content for the fallback part when the image is absent or not yet shown. Accepts attributes:class(:string)
value- Optional replacement for:fallbackinner content. Use:let={value}—valueis the imagesrc(ornil). Accepts attributes:class(:string)
Static loading placeholder for use with <.async_result> or when pending is true without a :loading slot.
Attributes
- Global attributes are accepted.
API
Requests whether the avatar image is loaded from the browser. Returns a Phoenix.LiveView.JS command.
Options: :respond_to — :server (default, avatar_loaded_response only), :both, or :client (avatar-loaded DOM only).
Examples
<.action phx-click={Corex.Avatar.loaded("my-avatar")} class="button button--sm">Loaded</.action>
<.action phx-click={Corex.Avatar.loaded("my-avatar", respond_to: :client)} class="button button--sm">
Loaded (client)
</.action>
Requests loaded state from the client. Pushes a LiveView event handled by the hook.
See loaded/2 for :respond_to.
Examples
def handle_event("avatar_loaded_response", %{"id" => id, "loaded" => loaded}, socket) do
{:noreply, assign(socket, :avatar_loaded, {id, loaded})}
end
Sets the avatar image URL from the client. Returns a Phoenix.LiveView.JS command.
Examples
<.action phx-click={Corex.Avatar.set_src("my-avatar", "https://example.com/x.png")} class="button button--sm">
Set src
</.action>
Sets the avatar image URL from the server. Pushes a LiveView event handled by the hook.
Examples
def handle_event("set_avatar", %{"url" => url}, socket) do
{:noreply, Corex.Avatar.set_src(socket, "my-avatar", url)}
end