fileUpload
Drag-and-drop upload zone with a hidden <input type="file">. Clicking or dropping files opens the picker. Requires pulse-ui.js for drag highlighting and click-to-open behaviour.
Basic
Drag & drop or browse
PNG, JPG, PDF up to 10 MB
fileUpload({ name: 'file', label: 'Upload file', hint: 'PNG, JPG, PDF up to 10 MB', event: 'change:setFile' })Accepted file types
Drag & drop or browse
PNG or JPG
fileUpload({ name: 'avatar', label: 'Profile photo', accept: 'image/*', hint: 'PNG or JPG' })Multiple files
Drag & drop or browse
Select one or more files
fileUpload({ name: 'docs', label: 'Attachments', multiple: true, hint: 'Select one or more files' })Error state
Drag & drop or browse
File must be under 10 MB
fileUpload({ name: 'file', label: 'Upload file', error: 'File must be under 10 MB' })Disabled
Drag & drop or browse
Uploads are currently unavailable
fileUpload({ name: 'file', label: 'Upload file', disabled: true, hint: 'Uploads are currently unavailable' })Reading the file in an action
Use the component inside a <form data-action="...">. The file is available in FormData under name.
Drag & drop or browse
// view
`<form data-action="upload" class="u-flex u-flex-col u-gap-4">
${fileUpload({ name: 'attachment', label: 'Attachment', accept: '.pdf,.doc,.docx', required: true })}
${button({ label: 'Upload', type: 'submit', variant: 'primary' })}
</form>`
// action
upload: {
onStart: (state) => ({ status: 'loading' }),
run: async (state, serverState, formData) => {
const file = formData.get('attachment') // File object
// process file...
},
onSuccess: (state) => ({ status: 'success' }),
onError: (state, err) => ({ status: 'error', message: err.message }),
}Live file name via mutation
Use event: 'change:mutationName' to capture the selected filename in state immediately — without a form submission.
Drag & drop or browse
// state
{ fileName: '' }
// mutation — e.target.files[0] gives the File object
setFile: (state, e) => ({ fileName: e.target.files[0]?.name ?? '' })
// view
fileUpload({ name: 'photo', label: 'Photo', accept: 'image/*', event: 'change:setFile' })
${state.fileName ? `<p class="u-mt-2 u-text-sm">${state.fileName}</p>` : ''}The file object itself cannot be stored in Pulse state — state must be serialisable. Store the filename or a preview URL (via
URL.createObjectURL) instead, and upload the file in an action via FormData.| Prop | Type | Default | |
|---|---|---|---|
name | string | — | Field name — file available in FormData under this key |
label | string | — | Visible label text |
hint | string | — | Helper text, e.g. accepted types and max size |
error | string | — | Validation error message |
accept | string | — | Accepted MIME types or extensions, e.g. image/* or .pdf,.docx |
multiple | boolean | false | Allow selecting multiple files |
required | boolean | false | |
disabled | boolean | false | |
event | string | — | data-event on the input — use change:mutationName to capture file selection in state |
id | string | — | Override the generated id |
class | string | — |