documentation / build
Upload components
Style the upload button and dropzone, or build your own picker on the upload hook.
import "@uploadfile/react/styles.css";Import the stylesheet once. Vue, Svelte, and Solid ship the same file at @uploadfile/vue/styles.css, @uploadfile/svelte/styles.css, and @uploadfile/solid/styles.css. The Nuxt module adds it for you. Skip the stylesheet if you use Tailwind CSS.
@import "tailwindcss";
@import "@uploadfile/core/tw/v4";
@source "../node_modules/@uploadfile/react/dist";import { withUf } from "@uploadfile/core/tw";
export default withUf({
content: ["./app/**/*.{ts,tsx}"],
});Both setups add the uf-* variants and tell Tailwind to scan the component package. For v4, point @source at the package you use, relative to the CSS file.
Each component marks its parts with data-uf-element and its state with data-state. The Tailwind variants uf-button, uf-allowed-content, uf-label, uf-upload-icon, and uf-clear-btn target the parts. uf-readying, uf-ready, and uf-uploading target the states.
<UploadButton
endpoint="imageUploader"
className="uf-button:bg-violet-600 uf-uploading:opacity-70 uf-allowed-content:text-zinc-500"
/>appearance sets classes or styles per part, and content replaces the text or elements inside each part. Both accept a function of the component state, which includes ready, isUploading, uploadProgress, and files.
<UploadDropzone
endpoint="imageUploader"
appearance={{
container: "rounded-xl border border-dashed p-8",
button: ({ isUploading }) => (isUploading ? "opacity-60" : ""),
}}
content={{
label: "Drop images here",
allowedContent: ({ ready }) => (ready ? "Up to 4 images, 4 MB each" : "Loading..."),
}}
/>"use client";
import { generateReactHelpers } from "@uploadfile/react";
import type { AppFileRouter } from "./api/uploadfile/core";
const { useUploadfile } = generateReactHelpers<AppFileRouter>();
export function AvatarPicker() {
const { startUpload, isUploading } = useUploadfile("imageUploader", {
onClientUploadComplete: (files) => console.log(files[0]?.ufsUrl),
onUploadError: (error) => alert(error.message),
});
return (
<input
type="file"
accept="image/*"
disabled={isUploading}
onChange={(event) => {
const files = Array.from(event.target.files ?? []);
if (files.length > 0) void startUpload(files);
}}
/>
);
}startUpload runs the same checks and transfer as the components. The Vue, Svelte, and Solid packages provide the same hook as useUploadfile or createUploadfile.