SutraUI.FileUpload (Sutra UI v0.4.0)
View SourceA 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 fromallow_upload/3.label- Label text for the dropzone.description- Hint text shown below the label.thumbnail- Show image previews for image entries. Defaults tofalse.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 withentry,upload, andcancel_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)}
endAccessibility
- 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"witharia-valuenow/min/max. - Error messages per entry are rendered inline.
Summary
Functions
Attributes
upload(:any) - Phoenix LiveView upload config from allow_upload/3. Defaults tonil.label(:string) - Label text for the dropzone. Defaults tonil.description(:string) - Hint text shown below the label. Defaults tonil.thumbnail(:boolean) - Show image previews for image entries. Defaults tofalse.accept(:any) - Deprecated. Configure accepted types in allow_upload/3. Defaults tonil.max_files(:any) - Deprecated. Configure max entries in allow_upload/3. Defaults tonil.class(:any) - Additional CSS classes. Defaults tonil.id(:string) - DOM id for the upload root. Defaults tonil.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.