FileUpload
Drop it here.
About
Dropzone with a queue of file rows in uploading, done and error states. Picked or dropped files come out through suiSelect; give it a url and it uploads them and shows real progress, or drive files from the host. Without url, a plain form posts the queued files under name. Use for receipts, CSV imports and logo upload.
Usage
Basic
accept is the native filter, as on <input type="file">; help is the line under the title; multiple lets one pick or drop queue several files. The zone is role="button" named "Upload files". Each row has its own "Remove {name}" button, and an uploading row is a progressbar named "Uploading {name}".
Queue states
files is a property holding the rows. A pick appends done rows and the host replaces the list to drive real progress; uploading shows a bar and a percent, error shows its message in place of the size.
Uploading to a url
Give it a url and it posts every accepted file itself, one request per file, and drives each row from the real upload progress. This example answers with a stub the page installs, so nothing leaves your browser.
When an upload fails
A failed request turns the row red and adds a retry control beside remove; suiUploadError carries the status and the body. The stub here refuses the first attempt and takes the second.
Image previews
An image row shows the image instead of the file-type icon. Set thumbnail on a row yourself for a file already on your server.
Compact and single file
compact tightens the dropzone padding for a side panel. Without multiple the zone takes one file, as a native file input does: the picker offers one and a drop of several keeps the first. That suits a logo or a signed form.
Disabled
disabled locks the zone and the row controls: the picker cannot open, a drop is ignored, and the zone leaves the tab order. Use it while a form saves.
Limits
accept, maxFileSize and fileLimit refuse rather than error: a refused file never enters the queue and comes out through suiReject, so the host decides how to say so. Size and count are checked on picks and drops alike; accept is re-applied only on a drop, because the browser already filtered a pick.
Events
suiSelect carries the native File objects that were accepted, suiReject carries the ones a rule refused, and suiRemove carries the row a remove control dropped. With no url set, wire suiSelect to your own upload and replace files with the rows it reports.
In a form
The element is form-associated. Without a url every queued file posts under name as a multipart entry, picked or dropped, and a removed row leaves the post. With a url the files go up on their own and the form posts nothing for them. required holds the submit until a file is queued.
Keyboard
| Key | Action |
|---|---|
| Enter Space | On the dropzone: opens the native file picker. |
API
<sui-file-upload>
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
accept | accept | stringstring | undefined | Native accept filter for the picker, e.g. ".pdf,.csv,image/*". Omit to allow any file. A dropped file that fails it is refused through suiReject; on a pick the browser has already applied it. | |
compact | compact | boolean | false | Tighter dropzone padding (16px instead of 26px 16px) for a side panel. |
disabled | disabled | boolean | false | Locks the zone and the row controls. The picker cannot open, a drop is ignored, the zone leaves the tab order, and the element posts nothing. A disabled fieldset or form does the same. An upload already in flight runs to its end. |
error | error | stringstring | undefined | Error message under the queue; paints the zone's edge in the danger tone and fails the form (customError). | |
fileLimit | file-limit | numbernumber | undefined | Most rows the queue may hold, counting rows already there. Omit for no limit. Files beyond it are refused through suiReject. | |
files | property only | SuiFileRow[] | [] | Queued rows (the reference demoFiles). Property, not attribute. Mutable: picks append rows, the remove control drops them, and url mode writes progress onto them as it uploads. |
help | help | stringstring | undefined | Help line under the dropzone title, as every field has one. Prose for the reader, so write the limits out in words; accept and maxFileSize are what the element enforces. Unset, the element says the size limit if there is one. It used to say "PDF, CSV, JPG, up to 25 MB" whatever it was configured to accept, which is one customer's upload form and was a lie on anybody else's. With no help and no limit there is no help line, because there is nothing true to say. | |
label | label | stringstring | undefined | Label above the dropzone; it also names the zone, before its own words. | |
maxFileSize | max-file-size | numbernumber | undefined | Largest accepted file in bytes (25 MB is 26214400). Omit for no limit. Checked on picks and drops alike; an over-size file is refused through suiReject and never enters the queue. | |
multiple | multiple | boolean | false | Allows more than one file per pick, as the native multiple does. Off by default, as on a native file input: the picker takes one file and a drop of several keeps the first. |
name | name | stringstring | undefined | Form control name. Without url every queued row that holds a file, picked or dropped, posts under it as a multipart entry, and a removed row leaves the post (send the form with enctype="multipart/form-data"). With url it names the field the element sends each file under, and the form posts nothing for them, since they have gone up already. Reflected: the form entry is built from the content attribute, and all three framework bindings set props. | |
required | required | boolean | false | A file must be queued for the surrounding form to be valid (valueMissing while the queue holds no row that has not failed). A disabled upload never holds the form. |
url | url | stringstring | undefined | Endpoint for the element's own upload. Set it and every accepted file is posted as it is queued, one request per file, with the row showing real progress. Leave it off and the host uploads through suiSelect and drives files itself. The limits apply either way: a refused file is never sent. |
Events
| Event | Detail | React | Vue | Description |
|---|---|---|---|---|
suiBeforeUpload | SuiUploadRequestDetail | onSuiBeforeUpload | @sui-before-upload | Fires in url mode once per file, with the request open and unsent. Set headers on xhr or add fields to body. |
suiProgress | SuiUploadProgressDetail | onSuiProgress | @sui-progress | Fires in url mode as a file goes up, at each whole percent. The row carries the same number, so listen only if something outside the queue shows it. |
suiReject | File[] | onSuiReject | @sui-reject | Fires when accept, multiple, maxFileSize or fileLimit refuses files; detail is the refused File objects. A refused file never enters the queue, so the host decides how to say so. |
suiRemove | SuiFileRow | onSuiRemove | @sui-remove | Fires when a row's remove control is used; detail is the removed row. |
suiSelect | File[] | onSuiSelect | @sui-select | Fires when files are chosen or dropped and pass every rule; detail is the accepted native File objects. Fires in url mode too, before the requests go out. |
suiUpload | SuiUploadResultDetail | onSuiUpload | @sui-upload | Fires in url mode when a file lands, with the server's status and body text. |
suiUploadError | SuiUploadResultDetail | onSuiUploadError | @sui-upload-error | Fires in url mode when a file fails to upload. The row turns to error with a retry control; status is 0 when the request never reached the server. |
Methods
| Method | Signature | Description |
|---|---|---|
setFocus() | setFocus() => Promise<void> | Moves keyboard focus to the dropzone. sui-form calls this to reach the first invalid control. |
showPicker() | showPicker() => Promise<void> | Opens the native file picker, as the native input's showPicker() does. |
upload() | upload() => Promise<void> | Sends every row that is not done yet, which is how a failed row is tried again. Needs url. |
Types
SuiFileRow interfaceOne queued file row. size is display text ("182 KB"); progress is 0-100 while uploading. | |||
|---|---|---|---|
name | string | ||
size? | string | ||
status | 'uploading' | 'done' | 'error' | ||
progress? | number | ||
error? | string | ||
file? | File | The file the row was made from. url mode keeps it so a failed row can be sent again. | |
thumbnail? | string | Image preview source. The element fills it in for an image it queued, with an object URL it revokes once no row in files holds it any more; set it yourself on a row you restored from a server. | |
SuiUploadProgressDetail interfaceDetail of suiProgress: how far one file has got. progress is 0-100 and only whole steps are reported. | |||
|---|---|---|---|
file | File | ||
loaded | number | ||
total | number | ||
progress | number | ||
SuiUploadRequestDetail interfaceDetail of suiBeforeUpload: one file's request, open and not yet sent. Set headers on xhr or add fields to body. | |||
|---|---|---|---|
file | File | ||
body | FormData | ||
xhr | XMLHttpRequest | ||
SuiUploadResultDetail interfaceDetail of suiUpload and suiUploadError: one finished upload. status is the HTTP status, or 0 when the request never reached the server. | |||
|---|---|---|---|
file | File | ||
status | number | ||
response | string | ||
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.
Color18
Typography1
Radius3
Elevation1
Motion3
Every name above is listed with its value and its role in Foundations.