# `PhoenixKitWeb.Components.MediaGallery`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.164/lib/phoenix_kit_web/components/media_gallery.ex#L1)

A general-purpose LiveComponent for selecting, ordering, previewing and removing
a set of images.

Generalizes the gallery + picker pattern so any PhoenixKit consumer can embed it
instead of re-implementing the plumbing. The component manages an ordered list of
file UUIDs and reports changes to the parent LiveView.

## Usage

    <.live_component
      module={PhoenixKitWeb.Components.MediaGallery}
      id="my-gallery"
      selected={@image_uuids}
      phoenix_kit_current_user={@current_user}
    />

    # Receive changes in parent LiveView
    def handle_info({PhoenixKitWeb.Components.MediaGallery, "my-gallery", {:changed, uuids}}, socket) do
      {:noreply, assign(socket, :image_uuids, uuids)}
    end

## Attrs

- `id` — required; used for element IDs and change notifications
- `title` — optional heading above the gallery
- `selected` — ordered list of file UUIDs (current selection); default `[]`
- `mode` — `:single` or `:multiple` (default `:multiple`)
- `cols` — grid columns for the thumbnail layout (default `4`). Either an
  integer 1..6, or a string of Tailwind grid-column classes for a responsive
  grid (e.g. `"grid-cols-4 lg:grid-cols-6 2xl:grid-cols-8"`). Plumbed straight
  through to `<.draggable_list>`.
- `featured_first` — when `true`, the first item in `:selected` renders a
  "Featured" badge in the top-left corner. Matches the
  `phoenix_kit_posts` post-creation convention where the first image is the
  featured one and drag-reordering changes the feature. Default `false` so
  existing consumers aren't surprised.
- `scope_folder_id` — folder scope passed to the picker
- `phoenix_kit_current_user` — required for upload in the picker
- `readonly` — when `true`, hides the pick button, remove buttons, and DnD;
  preview (lightbox) still works; default `false`
- `max_count` — integer upper bound on the number of selected images for
  `:multiple` mode; `nil` means unlimited. For `:single` mode the limit is
  always 1 (implied by `mode`). When the limit is reached, the "Add" tile is
  hidden entirely (not just disabled) and `apply_selection` refuses to exceed it.

## Change notifications — required host wiring (silent failure otherwise)

This is a `LiveComponent`, so it has no `handle_info` of its own: after
any change (pick / remove / reorder) it sends a **process message to the
host LiveView** via `send/2`:

    {PhoenixKitWeb.Components.MediaGallery, id, {:changed, ordered_uuids}}

The host MUST handle this (see the Usage example above) and persist
`ordered_uuids` — it is a *controlled* component: it renders whatever the
host passes back as `:selected`. Forget the handler and the user's
picks/reorders are silently dropped (no crash, no warning). Each host
stores the selection differently (its own field/assoc), so there is
intentionally no `use ...Embed` macro — the handling is yours to write.

## Reorder event contract

The thumbnail grid uses the canonical `<.draggable_list>` primitive
(`PhoenixKitWeb.Components.Core.DraggableList`), which fires the
`"reorder_images"` event with payload `%{"ordered_ids" => uuids}`.

Because `MediaGallery` is a LiveComponent, the grid is rendered with
`target={"##{@id}"}` so the `SortableGrid` hook routes the event via
`pushEventTo` to this component's own `handle_event/3` — not the host
LiveView. Each gallery's `id` is unique, so multiple galleries on the same
page never cross-deliver reorder events.

# `render`

---

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