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

Animated loading placeholder components (shimmer / skeleton screens).

Skeleton screens replace content areas while data is loading, preventing
layout shift and providing a smoother perceived loading experience than a
spinner. All components use Tailwind v4 `animate-pulse` — pure HEEx, no
JavaScript required.

## Sub-components

| Component         | Purpose                                                  |
|-------------------|----------------------------------------------------------|
| `skeleton/1`      | Base rectangle or circle placeholder block               |
| `skeleton_text/1` | Stack of text-line placeholders simulating a paragraph   |
| `skeleton_avatar/1`| Circular placeholder for avatar images                  |
| `skeleton_card/1` | Composite card-shaped placeholder (image + text lines)   |

## Basic shapes

    <%!-- Rectangle placeholder (for an image, header, or button) --%>
    <.skeleton class="h-4 w-full" />

    <%!-- Circle placeholder (for an avatar) --%>
    <.skeleton shape={:circle} width="40px" height="40px" />

## Dashboard card loading skeletons

Replace stat cards with skeletons while data loads:

    <%= if @loading do %>
      <div class="grid grid-cols-3 gap-4">
        <%= for _ <- 1..3 do %>
          <.skeleton_card />
        <% end %>
      </div>
    <% else %>
      <.metric_grid>
        <%= for stat <- @stats do %>
          <.stat_card title={stat.title} value={stat.value} />
        <% end %>
      </.metric_grid>
    <% end %>

## List item skeletons

Use `skeleton_avatar/1` with `skeleton_text/1` to match a user list:

    <%= if @loading do %>
      <div class="space-y-4">
        <%= for _ <- 1..5 do %>
          <div class="flex items-center gap-4">
            <.skeleton_avatar size="10" />
            <div class="flex-1">
              <.skeleton_text lines={2} />
            </div>
          </div>
        <% end %>
      </div>
    <% else %>
      <%= for user <- @users do %>
        <.user_row user={user} />
      <% end %>
    <% end %>

## Article / blog post skeleton

    <div class="space-y-4 max-w-2xl">
      <%!-- Hero image area --%>
      <.skeleton class="h-56 w-full" />
      <%!-- Title --%>
      <.skeleton class="h-8 w-3/4" />
      <%!-- Author line --%>
      <div class="flex items-center gap-2">
        <.skeleton_avatar size="8" />
        <.skeleton class="h-4 w-32" />
      </div>
      <%!-- Body paragraphs --%>
      <.skeleton_text lines={5} />
      <.skeleton_text lines={4} />
    </div>

## Table skeleton

Match the column widths of your real table:

    <table>
      <thead>...</thead>
      <tbody>
        <%= if @loading do %>
          <%= for _ <- 1..8 do %>
            <tr>
              <td class="p-4"><.skeleton class="h-4 w-8" /></td>
              <td class="p-4"><.skeleton class="h-4 w-40" /></td>
              <td class="p-4"><.skeleton class="h-4 w-24" /></td>
              <td class="p-4"><.skeleton class="h-4 w-20" /></td>
            </tr>
          <% end %>
        <% else %>
          ...real rows...
        <% end %>
      </tbody>
    </table>

# `skeleton`

Renders a single animated skeleton placeholder block.

Use `:rectangle` (default) for any block-level placeholder: image areas,
text lines, buttons, or card borders. Use `:circle` for avatar placeholders.

Size the skeleton with Tailwind classes via `:class`, or with explicit
pixel/rem values via `:width` and `:height`. Both can be used together.

## Examples

    <%!-- Full-width text line --%>
    <.skeleton class="h-4 w-full" />

    <%!-- Fixed-size image placeholder --%>
    <.skeleton class="h-40 w-full" />

    <%!-- Circle with explicit pixel size --%>
    <.skeleton shape={:circle} width="48px" height="48px" />

## Attributes

* `shape` (`:atom`) - Shape of the placeholder. `:rectangle` (default) for blocks and text lines; `:circle` for avatars. Defaults to `:rectangle`. Must be one of `:rectangle`, or `:circle`.
* `width` (`:string`) - CSS width applied as an inline style (e.g. `"200px"`, `"50%"`). When `nil`, width is controlled by the `class` attribute. Defaults to `nil`.
* `height` (`:string`) - CSS height applied as an inline style (e.g. `"48px"`, `"2rem"`). When `nil`, height is controlled by the `class` attribute. Defaults to `nil`.
* `class` (`:string`) - Additional CSS classes merged via `cn/1`. Use Tailwind `h-N w-N` to size the skeleton. Defaults to `nil`.
* Global attributes are accepted. HTML attributes forwarded to the root `<div>` element.

# `skeleton_avatar`

Renders a circular skeleton placeholder for avatar images.

The `:size` attribute maps directly to Tailwind's numeric sizing scale:

| size  | output classes | px size |
|-------|----------------|---------|
| `"6"` | `w-6 h-6`      | 24 px   |
| `"8"` | `w-8 h-8`      | 32 px   |
| `"10"`| `w-10 h-10`    | 40 px   |
| `"14"`| `w-14 h-14`    | 56 px   |

## Example

    <%!-- Default 40px avatar skeleton --%>
    <.skeleton_avatar />

    <%!-- 56px skeleton matching a "lg" avatar --%>
    <.skeleton_avatar size="14" />

## Attributes

* `size` (`:string`) - Tailwind size number that maps to both `w-N` and `h-N`. For example, `"10"` produces `w-10 h-10` (40px). Common values: `"6"` (24px), `"8"` (32px), `"10"` (40px), `"14"` (56px). Defaults to `"10"`.
* `class` (`:string`) - Additional CSS classes merged with the size-derived classes. Defaults to `nil`.

# `skeleton_card`

Renders a composite card-shaped skeleton with a header image area and text
lines below it.

Useful as a drop-in replacement for product cards, blog post cards, or
dashboard stat cards while their content is loading.

## Example

    <div class="grid grid-cols-3 gap-4">
      <%= for _ <- 1..3 do %>
        <.skeleton_card />
      <% end %>
    </div>

## Attributes

* `class` (`:string`) - Additional CSS classes applied to the card wrapper `<div>`. Defaults to `nil`.

# `skeleton_form`

Renders a form-shaped skeleton with label + input pairs.

Useful as a placeholder while a form's initial values are loading (e.g.
an edit form waiting for a record to be fetched).

## Example

    <%= if @loading do %>
      <.skeleton_form fields={6} />
    <% else %>
      <.my_form changeset={@changeset} />
    <% end %>

## Attributes

* `fields` (`:integer`) - Number of label + input field pairs to render. Defaults to `4`.
* `show_submit` (`:boolean`) - When `true`, renders a button skeleton at the bottom. Defaults to `true`.
* `class` (`:string`) - Additional CSS classes. Defaults to `nil`.

# `skeleton_list`

Renders a list of skeleton rows simulating a user list, contact list, or feed.

Each row has an optional avatar circle on the left and two text lines
(title + subtitle) on the right.

## Example

    <%= if @loading do %>
      <.skeleton_list items={8} />
    <% else %>
      <%= for user <- @users do %>
        <.user_row user={user} />
      <% end %>
    <% end %>

## Attributes

* `items` (`:integer`) - Number of list item rows to render. Defaults to `5`.
* `show_avatar` (`:boolean`) - When `true`, each row has a circular avatar placeholder on the left. Defaults to `true`.
* `class` (`:string`) - Additional CSS classes for the wrapper. Defaults to `nil`.

# `skeleton_profile`

Renders a profile-page-shaped skeleton.

Simulates the typical layout of a user profile: large avatar, name, bio,
and a row of stats (posts, followers, following).

## Example

    <%= if @loading do %>
      <.skeleton_profile />
    <% else %>
      <.user_profile user={@user} />
    <% end %>

## Attributes

* `class` (`:string`) - Additional CSS classes. Defaults to `nil`.

# `skeleton_table_row`

Renders skeleton rows for a table body.

Use inside a `<tbody>` while table data is loading. The `:columns` attr
controls how many cells to render per row.

## Example

    <tbody>
      <%= if @loading do %>
        <.skeleton_table_row columns={5} rows={8} />
      <% else %>
        <%= for row <- @rows do %>
          <tr>...</tr>
        <% end %>
      <% end %>
    </tbody>

## Attributes

* `columns` (`:integer`) - Number of cell placeholders per row. Defaults to `4`.
* `rows` (`:integer`) - Number of rows to render. Defaults to `5`.
* `class` (`:string`) - Additional CSS classes for the wrapper. Defaults to `nil`.

# `skeleton_text`

Renders a stack of skeleton lines simulating a paragraph of text.

The last line is always rendered at 75% width (`w-3/4`) to mimic the
natural way text rarely fills the entire last line of a paragraph.

## Example

    <%!-- Simulates 4 lines of body text --%>
    <.skeleton_text lines={4} />

## Attributes

* `lines` (`:integer`) - Number of text lines to render. Default: `3`. The last line is rendered at `w-3/4` to simulate natural text flow. Defaults to `3`.
* `class` (`:string`) - Additional CSS classes applied to the wrapper `<div>`. Defaults to `nil`.

---

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