Skip to main content
WireKit
Copy for LLM

File Upload

The <x-wirekit::file-upload> component is a drag-and-drop file dropzone with click-to-browse fallback. It displays a live list of selected files with their sizes.

Usage

Basic File Upload

Max 5 MB — PDF, DOC, or DOCX

Accepted File Types

The accept prop is passed straight through to the native <input type="file" accept="..."> attribute. The browser uses it as a hint in the file picker (and filters the "All files" vs "specific types" dropdown) — it is NOT a security boundary. A user can always bypass it via drag-and-drop or by choosing "All files". You MUST validate file types server-side in your Laravel validator (e.g. mimes:pdf,docx or mimetypes:application/pdf).

Three ways to specify accepted types

You can mix any of the following inside a single comma-separated string:

  1. File extensions — start with a dot: .pdf, .docx, .csv
  2. MIME types — full type string: application/pdf, image/png
  3. Wildcard groups — generic category: image/*, video/*, audio/*

Extensions are the friendliest because they match what users see in their file manager, but MIME types and wildcards are more precise and work better on mobile devices.

Common recipes

Use case accept value
Any image image/*
PNG or JPG only image/png,image/jpeg or .png,.jpg,.jpeg
PDF only application/pdf or .pdf
Office documents .pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx
CSV / spreadsheet import .csv,.xls,.xlsx,text/csv
Any video video/*
Any audio audio/*
Archives .zip,.tar,.gz,.rar,.7z
Camera capture on mobile image/*;capture=camera
Everything (default) (omit the prop)
Images only (PNG, JPG, WebP, GIF)

PNG, JPG, WebP, or GIF — up to 2 MB

Office documents (PDF, Word, Excel)

PDF, Word (.doc/.docx), or Excel (.xls/.xlsx) — up to 10 MB

CSV import

UTF-8 encoded CSV — first row is treated as column headers

Tip: Always pair accept with a human-readable hint that repeats the allowed formats and size limit. Users often ignore or miss the file picker filter.

Width

Like all WireKit form components, the file upload fills its container (w-full). Control the width via the parent element:

<div class="max-w-md">
    <x-wirekit::file-upload label="Resume" name="resume" accept=".pdf" />
</div>

See Input — Width for more layout examples (grid columns, mixed widths).

Multiple Files

Multiple Images

PNG, JPG, GIF up to 10 MB each

When multiple is true, the name attribute is automatically suffixed with [] so Laravel receives an array.

Long Filename Truncation

When a selected file has a name that is longer than the container can hold, the filename is truncated in the middle with an ellipsis () instead of wrapping onto a new line or pushing the file size / remove button out of view. This is achieved with truncate (CSS overflow: hidden; text-overflow: ellipsis; white-space: nowrap) combined with min-w-0 on the filename <span>, which lets the flex child shrink below its intrinsic content width.

The preview below sits in a deliberately narrow 20 rem container — drop a file with a long name (e.g. Q4-2026-final-budget-forecast-with-margin-analysis.pdf) into the dropzone to see the ellipsis in action:

Filename truncation in a narrow container

The filename span uses truncate min-w-0 so it can shrink below its intrinsic width; the size label and remove button both carry shrink-0 so they stay fully visible regardless of how long the filename is. Widen the container and the filename stops truncating and is shown in full.

Error State

File upload with an error message

File exceeds the 2 MB limit

Errors are shown below the dropzone with aria-invalid="true" + aria-describedby wiring.

Drag & Drop

Files dropped on the zone are automatically assigned to the underlying <input type="file"> via DataTransfer, and a native change event is fired so Livewire's wire:model bindings work unchanged.

Props

Prop Type Default Description
name string|null null Form field name (appends [] when multiple)
id string|null auto-generated Element id
multiple bool false Allow multiple file selection
accept string|null null Accepted MIME types or extensions
size string 'md' 'sm', 'md', 'lg'
disabled bool false Disabled state
label string 'Drop files here or click to browse' Dropzone label text
removeLabel string 'Remove :name' Accessible name template for each file's remove button. The :name placeholder is replaced with the file name at runtime; override it to localize or change the wording
hint string|null null Helper text below dropzone
error string|null null Error message (also reads from $errors)
scope string|null null Scoped personalization key

Accessibility

  • Native <input type="file"> preserved (visually sr-only) — full a11y support
  • <label> wraps the dropzone so click + keyboard focus work correctly
  • Error message linked via aria-describedby + aria-invalid="true"
  • Upload icon is aria-hidden="true" (label text describes the action)

Keyboard Interaction

Key Action
Tab Move focus to the file picker control
Enter / Space Open the system file dialog

Pitfalls

  • Don't omit accept="..." for typed uploads. Without accept, the OS file picker shows everything; users wander into binary files that the server rejects.
  • Don't bind wire:model.live to file inputs. Livewire already streams files via its dedicated upload pipeline — .live isn't needed and causes redundant requests.

Design Tokens

Token Used for
--text-wk-xs / --text-wk-sm Hint / metadata text
--color-wk-text-muted / --color-wk-text-subtle Hint + dropzone instruction text
--color-wk-bg-muted / --color-wk-bg-subtle Dropzone background + chip background
--color-wk-border-strong Dropzone border
--color-wk-border-error Error-state border
--color-wk-accent Active drag-over highlight
--color-wk-danger-text Error message
--color-wk-ring Focus ring
--ring-wk-width Focus ring width
--radius-wk-sm / --radius-wk-md / --radius-wk-lg Dropzone + chip border radius
--padding-wk-x-sm / --padding-wk-y-xs / --padding-wk-y-sm / --padding-wk-y-md / --padding-wk-y-lg Spacing
--transition-wk-duration Drag-over transition

Config Defaults

The defaults live in config/wirekit.php under components.file-upload. Override them globally:

'components' => [
    'file-upload' => ['size' => 'md', 'multiple' => true, 'accept' => 'image/*'],
],

Further Reading

Was this page helpful?

Voting requires cookies or local storage. What we store