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
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:
- File extensions — start with a dot:
.pdf,.docx,.csv - MIME types — full type string:
application/pdf,image/png - 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) |
PNG, JPG, WebP, or GIF — up to 2 MB
PDF, Word (.doc/.docx), or Excel (.xls/.xlsx) — up to 10 MB
UTF-8 encoded CSV — first row is treated as column headers
Tip: Always pair
acceptwith a human-readablehintthat 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
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:
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 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 (visuallysr-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. Withoutaccept, the OS file picker shows everything; users wander into binary files that the server rejects. - Don't bind
wire:model.liveto file inputs. Livewire already streams files via its dedicated upload pipeline —.liveisn'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/*'],
],