File Upload
shadcn-htmx/file-uploadFreeComponent
Styled label-wrapped native <input type="file"> with drag-and-drop, a filename/preview list, and a native <progress> bar. Submits via standard multipart POST. Ships in five flavours.
Live preview
live · rendered by the registry
Rendered by shadcn-htmx on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://shadcn-htmx.productdevbook.com/r/file-upload.jsonSource
1/** @jsxImportSource hono/jsx */2import { cn, type ClassValue } from "@/registry/lib/cn"34// File Upload — shadcn-htmx, htmx v4 + Tailwind v4.5//6// A styled <label>-wrapped native <input type="file"> with an optional7// drag-and-drop enhancement, a selected-file list (with image previews),8// and a native <progress> upload bar. It submits via a standard multipart9// POST — no custom transport — so it works with a plain <form> and degrades10// to a bare file picker when JavaScript is off.11//12// There is no "file upload" or "dropzone" element in the platform — the13// pieces are:14// - <input type="file"> + <label> — the picker + its accessible name.15// repos/mdn/files/en-us/web/html/reference/elements/input/file/index.md16// - Drag-and-Drop API (drop/dragover) + File API (input.files, FileList)17// for the optional drop-zone enhancement.18// repos/mdn/files/en-us/web/api/html_drag_and_drop_api/file_drag_and_drop/index.md19// - htmx multipart upload (hx-encoding="multipart/form-data") and20// hx-preserve to keep the selection across re-render-on-error swaps.21// repos/htmx/www/src/content/patterns/02-forms/03-file-upload.md22// repos/htmx/www/reference.md (hx-encoding, hx-preserve)23//24// Style analogues (matched exactly): registry/ui/input.tsx (the field /25// file:* affordance + focus-visible ring + .htmx-request dim) and26// registry/ui/progress.tsx (the native <progress> visual).27//28// The keyboard/behaviour contract (drop wiring + filename/preview list +29// reset) lives in public/site.js, scoped to [data-slot="file-upload"]; an30// inline boot script next to the root only marks it ready, so a server swap31// re-arms cleanly. None of it is required for the upload to work.3233const root =34 "group/file-upload grid w-full gap-3 " +35 // While a request triggered by/targeting this control is in flight,36 // htmx adds .htmx-request — dim like Input does.37 "[&.htmx-request]:opacity-70"3839const zone =40 "flex cursor-pointer flex-col items-center justify-center gap-2 rounded-md border border-dashed border-input bg-transparent px-6 py-8 text-center text-sm text-muted-foreground shadow-xs transition-[color,box-shadow] outline-none " +41 "dark:bg-input/30 " +42 // The visually-hidden <input> is the real focus target; mirror its focus43 // ring onto the styled label via :focus-within.44 "focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50 " +45 "hover:border-ring/60 hover:text-foreground " +46// … truncated
More from shadcn-htmx
All 83 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | shadcn-htmx | Components | Free | no deps | |
| Active Searchactive-search | shadcn-htmx | Components | Free | no deps | |
| Alertalert | shadcn-htmx | Components | Free | no deps | |
| Alert Dialogalert-dialog | shadcn-htmx | Components | Free | no deps | |
| Aspect Ratioaspect-ratio | shadcn-htmx | Components | Free | no deps | |
| Auto Gridauto-grid | shadcn-htmx | Components | Free | no deps | |
| Autocompleteautocomplete | shadcn-htmx | Components | Free | no deps | |
| Autosize Textareaautosize-textarea | shadcn-htmx | Components | Free | no deps |
