SutraUI.FileUpload (Sutra UI v0.4.0)

View Source

A drag-and-drop file upload component built on Phoenix LiveView uploads.

Wraps Phoenix's allow_upload/3 with a styled dropzone, per-file progress bars, image thumbnails, and file previews. Configure uploads in your LiveView, then pass the upload config.

Examples

# In your LiveView
def mount(_params, _session, socket) do
  {:ok,
   socket
   |> allow_upload(:documents,
     accept: ~w(.pdf .png),
     max_entries: 5,
     max_file_size: 10_000_000
   )}
end

# In your template
<.form for={@form} phx-change="validate" phx-submit="save">
  <.file_upload upload={@uploads.documents} label="Upload documents" />
</.form>

# Image upload with thumbnails
<.file_upload
  upload={@uploads.photos}
  label="Upload photos"
  description="JPG or PNG, max 5 files"
  thumbnail
/>

# Custom dropzone content
<.file_upload upload={@uploads.files}>
  <:drop_content>
    <span class="text-4xl">📁</span>
    <span>Drop your files here</span>
  </:drop_content>
</.file_upload>

# Custom preview content
<.file_upload upload={@uploads.documents}>
  <:entry :let={item}>
    <div class="flex items-center justify-between gap-3">
      <span class="truncate">{item.entry.client_name}</span>
      <button
        type="button"
        phx-click={item.cancel_event}
        phx-value-upload={item.upload.name}
        phx-value-ref={item.entry.ref}
      >
        Remove
      </button>
    </div>
  </:entry>
</.file_upload>

Attributes

  • upload - Phoenix LiveView upload config from allow_upload/3.
  • label - Label text for the dropzone.
  • description - Hint text shown below the label.
  • thumbnail - Show image previews for image entries. Defaults to false.
  • class - Additional CSS classes.
  • id - Optional DOM id for the upload root. Defaults to {ref}-dropzone.
  • cancel_event - Event emitted when removing a file. Defaults to "cancel-upload".

Accepted file types, max entries, and max file size belong in allow_upload/3; the component reads the resulting upload config.

Slots

  • :drop_content - Custom content for the dropzone. Falls back to the default icon + label/description.
  • :entry - Custom preview for each selected file. Receives a map with entry, upload, and cancel_event.

Event Handling

def handle_event("validate", _params, socket), do: {:noreply, socket}

def handle_event("save", _params, socket) do
  consumed =
    consume_uploaded_entries(socket, :documents, fn meta, entry ->
      dest = Path.join("priv/uploads", Path.basename(entry.client_name))
      File.cp!(meta.path, dest)
      {:ok, dest}
    end)

  {:noreply, put_flash(socket, :info, "Uploaded #{length(consumed)} files")}
end

def handle_event("cancel-upload", %{"upload" => upload, "ref" => ref}, socket) do
  {:noreply, cancel_upload(socket, String.to_existing_atom(upload), ref)}
end

Accessibility

  • The dropzone is a <label> wrapping the file input — clicking anywhere opens the file picker.
  • The file input is visually hidden but keyboard-focusable; focus rings appear on the dropzone.
  • Each entry's cancel button has a descriptive aria-label.
  • Progress bars use role="progressbar" with aria-valuenow/min/max.
  • Error messages per entry are rendered inline.

Summary

Functions

file_upload(assigns)

Attributes

  • upload (:any) - Phoenix LiveView upload config from allow_upload/3. Defaults to nil.
  • label (:string) - Label text for the dropzone. Defaults to nil.
  • description (:string) - Hint text shown below the label. Defaults to nil.
  • thumbnail (:boolean) - Show image previews for image entries. Defaults to false.
  • accept (:any) - Deprecated. Configure accepted types in allow_upload/3. Defaults to nil.
  • max_files (:any) - Deprecated. Configure max entries in allow_upload/3. Defaults to nil.
  • class (:any) - Additional CSS classes. Defaults to nil.
  • id (:string) - DOM id for the upload root. Defaults to nil.
  • cancel_event (:string) - Event emitted when removing a file. Defaults to "cancel-upload".
  • Global attributes are accepted. Additional HTML attributes.

Slots

  • drop_content - Custom content for the dropzone. Falls back to default icon + label.
  • entry - Custom preview for each selected file.