Livewire UI
Livewire UI
Livewire components and themes
Laracrate ships an optional Livewire UI layer. The core (models, storage, pipeline, HTTP endpoints) works without Livewire, so you can ignore this section entirely and build your own front end against the methods in the "Working with files from your models" section. If you do use Livewire, these components wire the model trait, collection config, and upload flow together for you.
The components register only when Livewire is installed (registerLivewireComponents() no-ops otherwise). Each one resolves a Blade theme at render time, so the look is fully swappable.
Minimal example: a single-file uploader for a user avatar.
<livewire:laracrate-uploader :model="$user" collection="avatar" />
The six components
All six are registered in LaracrateServiceProvider with the tag names below. They split into two families: card uploaders (single file, in-place preview) and dropzones (presigned direct upload to R2/S3, see the "Upload modes" and "HTTP endpoints" sections). Each family has an instant variant and a deferred variant. Deferred means selecting a file stages it for review and only persists when the user confirms.
| Tag | Class | Files | Behavior | Use case |
|---|---|---|---|---|
laracrate-uploader |
LaracrateUploader |
single | Instant: selecting a file calls setFile() immediately |
Avatar, logo, cover image |
laracrate-uploader-deferred |
LaracrateUploaderDeferred |
single | Deferred: preview, then submit() to persist or cancel() to discard |
Same as above when you want an explicit confirm step |
laracrate-dropzone |
LaracrateDropzone |
multiple | Instant direct upload per file, fires per-file and batch events | Galleries, document libraries |
laracrate-dropzone-deferred |
LaracrateDropzoneDeferred |
multiple | Deferred: queue files, review, then upload the whole batch. Supports file slots and an integrated slot picker | Forms where files are tied to slots or categories |
laracrate-dropzone-single |
LaracrateDropzoneSingle |
single | Instant direct upload, one file, in-place preview | One large file (a video, a PDF) too big for the card uploader |
laracrate-dropzone-single-deferred |
LaracrateDropzoneSingleDeferred |
single | Deferred single direct upload, in-place preview | Same, with an explicit confirm step |
The card uploaders (laracrate-uploader, laracrate-uploader-deferred) push the file through Livewire's temporary upload, so the binary passes through PHP. The dropzones upload straight to your disk with a presigned PUT and the binary never touches PHP. Pick the dropzone variants for large files.
Props
Both card uploaders accept the same props:
| Prop | Type | Default | Purpose |
|---|---|---|---|
model |
Eloquent model | required | The model the file belongs to (must use the HasFiles trait) |
collection |
string | required | Collection name as declared on the model |
variant |
string | null |
Variant to show in the preview (falls back to the master, then the collection placeholder) |
theme |
string | null |
Theme name (falls back to laracrate.ui.default_theme) |
layout |
string | row |
row or portrait |
rounded |
string | null |
Override preview rounding: none, sm, md, lg, xl, 2xl, 3xl, full |
The dropzone components share model, collection, and theme, plus their own props. Common ones across the dropzones: contextKey (an opaque identifier echoed back in the laracrate-file-uploaded event so you can route a file when several widgets share a page), folderId (target folder, see the "Folders" section), persistQueue, and maxFiles. LaracrateDropzoneDeferred adds slot support (slots, slotOptions, slotLabel, slotPlaceholder, slotOptional, selectedSlotId), a creator override (creator, or creatorType plus creatorId), hideActions, and a layout of grid or list. The single dropzones add hideExisting; the single deferred adds hideActions. See the "File slots" section for slot semantics.
Immediate vs deferred
Instant uploader, persists on selection:
<livewire:laracrate-uploader :model="$user" collection="avatar" theme="ios" variant="medium" />
Deferred uploader, shows a preview and waits for the user to confirm:
<livewire:laracrate-uploader-deferred :model="$user" collection="avatar" theme="studio" layout="portrait" />
A deferred multi-file dropzone, queue then batch upload:
<livewire:laracrate-dropzone-deferred :model="$organization" collection="gallery" theme="studio" />
All components dispatch browser events you can listen for: laracrate-file-uploaded (per file, with collection, fileId, and contextKey), laracrate-file-deleted or laracrate-file-removed, and on the dropzones laracrate-batch-completed (with ok and error counts). The deferred dropzone also dispatches laracrate-file-rejected when a file is refused by the collection or a slot quota. See the "Events" section for the server-side events fired during processing.
Themes and layouts
There are 11 themes: default, brutalist, material, ios, glassmorphism, neon, minimal, neumorphism, chatgpt, claude, and studio. Each card-uploader theme ships in 2 layouts, row and portrait, as resources/views/uploader/themes/{theme}/{row,portrait}.blade.php. The dropzone families resolve a single Blade per theme (for example dropzone/themes/{theme}.blade.php) and fall back to default when a theme has no matching view.
Set the project-wide default in config (the theme prop overrides it per component):
// config/laracrate.php 'ui' => [ 'default_theme' => env('LARACRATE_THEME', 'default'), ],
LARACRATE_THEME=studio
Customizing views
Publish the package views to override any theme or write a new one:
php artisan vendor:publish --tag=laracrate-views
The views land in resources/views/vendor/laracrate/. Edit a theme in place, or add a new theme by creating uploader/themes/{name}/row.blade.php and uploader/themes/{name}/portrait.blade.php (create matching files under dropzone/themes/, dropzone-single/themes/, etc. if you want the new theme available to those components too). Run php artisan view:clear after editing Blade files. The view contract (the variables each theme receives, such as $config, $file, $state, $previewUrl, $acceptAttr, $maxSizeKb, $pollMs, $roundedClass) is the same for every theme; copy an existing theme as your starting point.
Localization
The UI strings used by the Livewire components are translatable through the laracrate translation namespace, loaded by the service provider via loadTranslationsFrom(__DIR__ . '/../lang', 'laracrate'). The package ships English (lang/en/uploader.php) and Spanish (lang/es/uploader.php) out of the box, and resolves strings against your app's active locale.
Reference a string with the namespaced key:
{{ __('laracrate::uploader.upload') }}
The strings live in the uploader group. A sample of the keys (see the source files for the full list):
| Key | English | Spanish |
|---|---|---|
upload |
Upload file | Subir archivo |
select |
Select file | Seleccionar archivo |
replace |
Replace | Reemplazar |
delete |
Delete | Eliminar |
delete_confirm |
Delete this file? | ¿Borrar este archivo? |
submit |
Upload | Subir |
cancel |
Cancel | Cancelar |
uploading |
Uploading... | Subiendo... |
processing |
Processing | Procesando |
failed |
Error | Error |
slot_placeholder |
Unclassified | Sin clasificar |
max_size |
max :size MB | máx :size MB |
Keys like max_size and max_size_capital take a :size placeholder.
Overriding strings
Publish the translation files into your app, then edit them:
php artisan vendor:publish --tag=laracrate-translations
The files land in lang/vendor/laracrate/{locale}/uploader.php. Any key you define there overrides the package default for that locale; keys you leave out fall back to the package.
Adding a locale
Create lang/vendor/laracrate/{locale}/uploader.php for the new locale (copy en/uploader.php and translate the values, keeping the keys), then set your app locale. For example, to add French, add lang/vendor/laracrate/fr/uploader.php and the components will pick it up when app()->getLocale() returns fr.