Blade components you install and own.
Forms, date pickers, tables, modals and more for Laravel. One Artisan command copies the Blade, JavaScript and Tailwind CSS into your app. Plain Blade with a small vanilla JS file per component: no Livewire or Alpine needed, no package at runtime, and they work inside Livewire 3 and 4 components too.
php artisan larawell:add date-range-picker
Install in three steps
For Laravel 12 and 13 with Vite and Tailwind CSS v4, which new Laravel apps have out of the box.
-
Require the package
It only does the copying, so it can stay a dev dependency. Your app never needs it at runtime.
Terminalcomposer require --dev larawellui/larawellui -
Add the components you need
Name the components, or run it with no names to pick from a list. It copies each one and what it depends on, rewrites the PHP namespaces to yours and adds the JS and CSS imports. It checks for Tailwind CSS 4.1+ before writing anything. Run it again with --installed to pick up updates: files you haven't edited get the new version, files you have are skipped and reported, and larawell:diff shows what you'd miss. Commit larawellui.lock, which keeps track.
Terminalphp artisan larawell:add datepicker table -
Build your assets and use them
Then write the tag like any other Blade component.
Terminal, then Bladenpm run build <x-widget.datepicker name="start_date" label="Start date" />
Works with Livewire
Not needed, but supported: every component is checked in a browser inside Livewire 3 and 4 components.
- Form controls bind with
wire:model, no name needed, and show the property's value and its validation errors after every render. - What someone did stays as they left it through a render: an open modal or menu, a panel they opened, a running stopwatch, files they picked.
- The component shows toasts and opens or closes modals with
$this->dispatch(). - Components a render or
wire:navigatebrings in set themselves up. Each one's page has a Livewire example under Usage.
<form wire:submit="save">
<x-widget.text-input label="Email" type="email" wire:model="email" />
<x-widget.datepicker label="Start date" wire:model.live="start" />
<x-widget.button type="submit">Save</x-widget.button>
</form>
// In the component, once it's saved
$this->dispatch('toast', type: 'success', message: 'Saved.');
Ready for AI agents
Agents get the same catalogue in a form they can read. Each component's entry has its install command, props, working examples and full source, so an agent can add a component or write it in by hand.
- /llms.txt
- An index of every component, for agents that follow the llms.txt convention.
- /r/index.json
- Every component, with a link to its full entry.
- /r/datepicker.json
- One component's full entry: install command, props, examples and source.
- php artisan larawell:list --json
- The same catalogue offline, from the installed package.
- php artisan larawell:mcp
- An MCP server in your app: the catalogue, what this app has installed and edited, and installing with a dry run first.
Components
Each one brings what it depends on, server side included. Adding the date picker also adds the field frame and icon it's built from, plus validation rules such as MinimumAge in App\Rules.
- <x-widget.accordion> Disclosure panels on <details>, as tinted panels, a bordered list or cards. Panels sharing a name open one at a time. The menu variant groups links in a sidebar that scrolls on its own and opens at the current page. Works inside Livewire components: a render updates what's inside and leaves panels open or shut as they were. Brings icon
- <x-widget.alert> Messages that stay on the page, in info, success, warning and error, with a title, actions and an optional dismiss button. flash="status" shows the session message Laravel's auth screens set. Includes an error summary for the top of a form that links each validation error to its field. Works inside Livewire components. Brings icon
- <x-widget.button> Button or link in primary, secondary, tertiary, danger, neutral and link variants, with sizes, icons, icon-only buttons and a loading state. Guards forms against double submits. Includes a back link. Works inside Livewire components, wire:submit forms included. Brings icon
- <x-widget.clock> Live clocks: digital and analog, world clocks across timezones, countdowns to a date, and a stopwatch or timer. First paint from the server, then they tick in the browser. Works inside Livewire components: they keep ticking, and a running stopwatch keeps running, through renders. Brings button, icon
- <x-widget.dropdown> Menu button on the native popover: row actions, account menus, "More" buttons. Items are links, buttons, or forms that submit with any method (a delete comes with its CSRF token), and confirm="…" asks with modal.confirm() first. Arrow keys, Home/End and type-to-jump, flips above when there's no room, and never clipped by a table or a modal. Works inside Livewire components: items take wire:click, confirm included. Brings button, icon, modal
- <x-widget.captcha> An image captcha, inline or stacked large above the answer, with an optional audio version and a refresh button. Or Cloudflare Turnstile, reCAPTCHA or hCaptcha, checked on the server with the Captcha rule. In Livewire the image (or the provider's widget) stays put through every render, so the code being answered never changes under you. Brings field, icon
- <x-widget.checkbox> A checkbox with a label or a label slot, a description, and an optional value for when it is off. Works with Livewire wire:model, as one box or a list on an array. Brings field, icon
- <x-widget.datepicker> Single date field with a calendar popover. Submits Y-m-d; validate with NotAfterToday, or MinimumAge for birthday. Works with Livewire wire:model, name optional. Brings field, icon
- <x-widget.date-range-picker> Start/end date picker with a multi-month popover. Submits two Y-m-d fields; validate them with NotAfterToday. Works with Livewire: wire:model binds an array's start and end. Brings button, datepicker, field, icon
- <x-widget.file-upload> File uploads on a real file input: a drag-and-drop dropzone (single or multiple, with a file list and remove), a compact button, and an image or avatar picker with preview. Checks type and size in the browser from accept and max-size, and with upload-url uploads each file straight away with a progress bar and submits the stored ids. Works with Livewire wire:model. Brings field, icon
- <x-widget.number> Digits only, with a set number of decimals, prefix, suffix and an action slot. Optional -/+ stepper within min and max, negatives, and thousands grouping. Accepts a decimal comma and still submits 12.50. Works with Livewire wire:model, which always gets the plain number. Brings field, icon
- <x-widget.otp> One-time passwords in one box per character, digits or letters, with a pasted code filling them all. Filled, outline or underline boxes, groups with a dash between, and masked for a PIN. Submits one value. Works with Livewire wire:model. Brings field
- <x-widget.password> A password field with a show/hide button and a Caps Lock warning. For new passwords, a live checklist of your rules. Never renders the value back into the page. Works with Livewire wire:model. Brings field, icon
- <x-widget.phone> A country picker with flags and dial codes, plus the number. Submits one international number, +60123456789. Works with Livewire wire:model. Brings field, icon, search
- <x-widget.radio> A group of radio buttons in a fieldset, with descriptions and disabled options. Works with Livewire wire:model. Brings field
- <x-widget.search> A search box that fills itself from the query string, in two sizes, with a clear button, the icon at either end and an optional keyboard shortcut. It searches as you type in a table's filters slot or with Livewire's wire:model.live; on its own it submits its form. Brings field, icon
- <x-widget.select> A styled select with keyboard support, type-to-jump and optional search. Single or multiple, and clearable. Options can carry meta (a balance, a count) shown beside them. Works with Livewire wire:model, including options that change between renders. Brings field, icon, search
- <x-widget.switch> An on/off switch that submits like a checkbox and is announced as a switch. Three sizes, an optional tick and cross, before or after its text, or as a card. Works with Livewire wire:model. Brings field, icon
- <x-widget.text-input> A text field with label, hint and error, filled back from the session after a failed submit. Takes any input type, plus prefix, suffix and a leading icon. Works with Livewire wire:model, name optional. Password, number, select and the other form controls are components of their own. Brings field, icon
- <x-widget.textarea> Grows with its content, or resizes by dragging. Optional character counter. Works with Livewire wire:model. Brings field
- <x-widget.time-picker> A time of day, four ways: a list of times step minutes apart, hour and minute columns, segments typed straight into the field, or a grid of slots for bookings. Within min and max, on the locale's 12- or 24-hour clock, and always submits HH:MM. Works with Livewire wire:model, name optional. Brings field, icon
- <x-widget.verification-code> A single field for a verification code: digits only, or letters too, cut to its length. For codes typed in one go; see the OTP for one box per character. Works with Livewire wire:model. Brings field
- <x-widget.field> Use this to wrap a control of your own so it matches the rest: the same label, box, error and hint, required mark and character counter, and an error that clears the moment the value changes. It's the frame every form control here is built on, so you never need it around those; they already have it. Works in Livewire around a wire:model control. Brings icon
- <x-widget.icon> Small SVG icons the other components use: chevrons, close, calendar, search and more. Pass a name; size and colour come from classes.
- <x-widget.modal> Dialogs on <dialog>: centred in four sizes or full screen, drawers from either side or the bottom, and a bottom sheet on phones. Pinned header and footer, Esc and backdrop close, focus return, scroll lock, and modal.confirm() for quick yes/no questions. Works inside Livewire components: it stays open through renders, and opens or closes on modal-open and modal-close events. Brings button, icon
- <x-widget.pagination> Paginator links in seven styles: drawer (bottom sheet of pages), numbers, segmented numbers, jump-to-page, table footer with rows per page, a summary with previous/next, and load more. In a Livewire component (WithPagination) every style changes page in place. Brings button, icon, modal
- <x-widget.price-roll> Odometer-style price that rolls its digits when data-value changes, with an optional change badge (since a previous price), trend colours that can be inverted or switched off, and before/after slots for your own markup. Formats with Intl on both server and client. Works inside Livewire components: a render with a new value rolls to it.
- <x-widget.progress> Progress bars, rings and stacked usage bars. Values in your own units, indeterminate and striped states, and progress.set() to update one from JavaScript. For step-by-step flows, see the stepper. Works inside Livewire components, wire:poll included.
- <x-widget.stepper> Step indicator for multi-step flows like checkout and onboarding: bars, dots, chevrons, or labelled steps (across or stacked with descriptions) that can link back, be locked, optional or need attention. Works inside Livewire components: it follows the current step through renders. Brings icon
- <x-widget.table> Data table for arrays or paginators: sortable columns (one or several at once), a Columns menu to show and hide columns, a totals row, a filters toolbar that filters in place with option counts (dimmed rows or skeleton while loading, optional in-memory cache), row selection with bulk actions, clickable and expandable rows, status badges, a row-actions menu, compact density, sticky header, stacked cards on phones, loading placeholders, drawer/numbers/jump/infinite pagination and an empty state. Brings button, dropdown, icon, pagination, search, select
- <x-widget.tabs> Tabs that switch between panels on the page: underlined, underlined and tinted, pills, a segmented track, or stacked beside the panel. Icons and counts on tabs, disabled ones, links as tabs for page navigation, sideways scrolling when there are too many, and remember to keep the open tab in the URL. The arrow keys move between them. Works inside Livewire components, with wire:model for the open tab. Brings icon
- <x-widget.toast> Notifications that appear in a corner and close themselves. Show them from a controller with a session flash, or from JavaScript. From Livewire, dispatch a toast event; flashes survive wire:navigate.
- <x-widget.tooltip> A short label or hint on an element, shown when the pointer rests on it or it gets keyboard focus, and hidden on Esc. On any side, moving to the other when there's no room, and never clipped by a table or a modal. Read out by screen readers as the element's description. Works inside Livewire components. Brings icon
- <x-widget.tooltip-cursor> A tooltip that follows the pointer over its element, for charts, maps and large areas where a label pinned to one edge would be far from what's pointed at. Moves to the other side of the pointer near the window's edges; with the keyboard it sits under the focused element. Hidden on Esc, read out by screen readers, never clipped. For a label pinned to an element, see the tooltip. Works inside Livewire components. Brings icon
Questions
- Is LarawellUi the same as laravel/ui?
- No. laravel/ui is the Laravel team's older package that scaffolds Bootstrap, Vue or React login pages. LarawellUi is a separate, independent project: a catalogue of Blade and Tailwind CSS v4 components that one Artisan command copies into your app.
- How is it different from a starter kit or a component package?
- A starter kit sets up a new app once. A component package stays installed and you call its components. LarawellUi copies each component's Blade, JavaScript and CSS into your existing app, so you can edit them like your own code, and it needs no Livewire or Alpine.
- Does my app need LarawellUi at runtime?
- No. The package only does the copying, so it can stay a dev dependency. Once a component is copied in, it runs without it.
- Is it free?
- Yes. LarawellUi is open source and MIT licensed.
Free, and staying free
LarawellUi is MIT licensed and built in spare time. If a component saved you an afternoon, a coffee helps pay for new components, fixes and keeping up with Laravel and Tailwind releases.