File Upload

Live Demos Hub
GitHub ↗

File Upload

Interactive production-grade hypermedia component for HTMXUI.

Interactive Preview

Click to upload or drag and drop

SVG, PNG, JPG or GIF (MAX. 800x400px)

HTML Source

<!-- 
  Component: file-upload.html
  Configurable State: themeColor ('primary'|'secondary'|'destructive'), size ('sm'|'md'|'lg'), isOpen (boolean)
  Usage: Bind styles dynamically using hx-class="{ 'bg-primary': themeColor === 'primary' }" or hx-style="{ width: size === 'lg' ? '100%' : 'auto' }"
-->
<!-- Drag and Drop File Upload Component -->
<!-- Uses HTMX to instantly upload files on drop without JS. The backend handles the file and returns the updated state. -->
<div hx-ext="reactive" hx-state="{ themeColor: \'primary\', size: \'md\', isOpen: false }"  
  class="flex flex-col items-center justify-center w-full h-64 border-2 border-dashed border-border rounded-lg bg-muted/50 hover:bg-muted transition-colors cursor-pointer group"
  hx-post="{upload_url}"
  hx-trigger="drop"
  hx-encoding="multipart/form-data"
  hx-target="this"
  hx-swap="outerHTML"
  ondragover="event.preventDefault(); this.classList.add('border-primary', 'bg-accent')"
  ondragleave="this.classList.remove('border-primary', 'bg-accent')"
  ondrop="event.preventDefault(); this.classList.remove('border-primary', 'bg-accent'); htmx.trigger(this, 'drop', { files: event.dataTransfer.files })"
>
  <div class="flex flex-col items-center justify-center pt-5 pb-6 pointer-events-none">
    <svg class="w-10 h-10 mb-4 text-muted-foreground group-hover:text-primary transition-colors" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 16">
      <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"/>
    </svg>
    <p class="mb-2 text-sm text-muted-foreground"><span class="font-semibold text-foreground">Click to upload</span> or drag and drop</p>
    <p class="text-xs text-muted-foreground">SVG, PNG, JPG or GIF (MAX. 800x400px)</p>
  </div>
  <!-- Hidden input allows fallback click-to-select behavior -->
  <input type="file" name="file" class="hidden" 
    hx-post="{upload_url}"
    hx-trigger="change"
    hx-encoding="multipart/form-data"
    hx-target="closest div"
    hx-swap="outerHTML"
  />
</div>