Liking cljdoc? Tell your friends :D

x-file-upload

A drag-and-drop file upload zone with click-to-browse, file list with optional image thumbnails, file validation, and form integration. Emits File objects via events — the app handles the actual upload.

Tag name

<x-file-upload>...</x-file-upload>

Observed attributes

AttributeTypeDefaultDescription
acceptstring""File type filter (MIME types, extensions, wildcards)
multiplebooleanfalseAllow multiple files
max-sizenumber(none)Max file size in bytes per file
max-filesnumber(none)Max number of files (with multiple)
disabledbooleanfalseDisables the component
requiredbooleanfalseRequired for form validation
namestring""Form field name

Accept format

Comma-separated tokens: MIME types (image/png), wildcards (image/*), or extensions (.pdf).

accept="image/*"
accept=".pdf,.doc,.docx"
accept="image/png,image/jpeg"

Properties (camelCase, reflect attributes)

PropertyTypeReflected attributeNotes
acceptstringaccept
multiplebooleanmultiple
maxSizenumbermax-size
maxFilesnumbermax-files
disabledbooleandisabled
requiredbooleanrequired
namestringname
filesFile[]Read-only, returns copy of current file list

Events

x-file-upload-select

Fired when files are added (after validation).

PropertyValue
bubblestrue
composedtrue
cancelablefalse
detail.filesArray of accepted File objects
detail.rejectedArray of {file, reason} for rejected files

x-file-upload-remove

Fired when a file is removed from the list.

PropertyValue
bubblestrue
composedtrue
cancelablefalse
detail.fileThe removed File object
detail.remainingArray of remaining File objects

Slots

SlotDescription
(default)Placeholder content shown in the drop zone

Shadow parts

PartDescription
drop-zoneMain interactive drop/click area
drag-overlayOverlay shown during drag-over
file-listContainer for file items
file-itemIndividual file row
thumbnailImage preview (images only, via blob URL)
file-nameFile name text
file-sizeFormatted file size text
removeRemove button per file
live-regionAccessibility announcements (visually hidden)

CSS custom properties

PropertyDefaultDescription
--x-file-upload-bgvar(--x-color-surface)Drop zone background
--x-file-upload-fgvar(--x-color-text)Text color
--x-file-upload-mutedvar(--x-color-text-muted)Muted text color
--x-file-upload-border2px dashed var(--x-color-border)Drop zone border
--x-file-upload-border-hover2px dashed var(--x-color-primary)Hover/drag border
--x-file-upload-drag-bgrgba(59,130,246,0.05)Drag-over background tint
--x-file-upload-radiusvar(--x-radius-md, 8px)Border radius
--x-file-upload-paddingvar(--x-space-lg, 24px)Drop zone padding
--x-file-upload-thumb-size48pxThumbnail dimensions
--x-file-upload-item-bgvar(--x-color-surface)File item background
--x-file-upload-remove-colorvar(--x-color-text-muted)Remove button color
--x-file-upload-remove-hovervar(--x-color-danger)Remove button hover color

Accessibility

  • Drop zone has role="button" and tabindex="0"
  • Enter/Space on drop zone opens the file picker
  • Remove buttons have aria-label="Remove {filename}"
  • File count changes announced via aria-live="polite" region
  • Disabled state: aria-disabled="true", tabindex="-1"

Thumbnails

Image files (image/*) automatically get a thumbnail preview via URL.createObjectURL(). Blob URLs are revoked when files are removed or the component disconnects.

File validation

Files are validated on add (drop or browse):

  • Type: checked against accept attribute
  • Size: checked against max-size attribute
  • Count: checked against max-files attribute (with multiple)

Rejected files are included in the x-file-upload-select event's detail.rejected array with a reason string.

Form integration

  • formAssociated: true — participates in form submission
  • Files submitted as FormData entries under the name attribute
  • required validation via ElementInternals
  • Responds to form.reset() (clears all files)
  • Responds to fieldset.disabled

Usage examples

Basic image upload

<x-file-upload accept="image/*" multiple>
  <p>Drop images here or click to browse</p>
</x-file-upload>

Constrained upload

<x-file-upload accept=".pdf" max-size="10485760" max-files="3" multiple>
  <p>Upload up to 3 PDFs (max 10MB each)</p>
</x-file-upload>

In a form

<form>
  <x-file-upload name="attachments" required multiple accept="image/*,.pdf">
    <p>Attach files</p>
  </x-file-upload>
  <button type="submit">Submit</button>
</form>

Listening for events

const uploader = document.querySelector('x-file-upload');

uploader.addEventListener('x-file-upload-select', e => {
  console.log('Accepted:', e.detail.files);
  console.log('Rejected:', e.detail.rejected);
  // Upload accepted files via fetch/XHR
});

uploader.addEventListener('x-file-upload-remove', e => {
  console.log('Removed:', e.detail.file.name);
  console.log('Remaining:', e.detail.remaining.length);
});

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close