GitHub

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
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.
PropTypeDefault
namestringField name — file available in FormData under this key
labelstringVisible label text
hintstringHelper text, e.g. accepted types and max size
errorstringValidation error message
acceptstringAccepted MIME types or extensions, e.g. image/* or .pdf,.docx
multiplebooleanfalseAllow selecting multiple files
requiredbooleanfalse
disabledbooleanfalse
eventstringdata-event on the input — use change:mutationName to capture file selection in state
idstringOverride the generated id
classstring