artisanpack-ui/livewire-ui-components
ArtisanPack UI Livewire UI Components offers 70+ responsive, accessible Livewire components styled with daisyUI and Tailwind CSS. Built for the TALL stack with Livewire 3/4 support, customizable themes, and an interactive installer to speed up Laravel app development.
Install in one pass
composer require artisanpack-ui/livewire-ui-components
php artisan livewire-ui-components:install # interactive
npm run dev
The installer is interactive and will typically publish config/theme assets and wire up daisyUI in your Tailwind config. Answer carefully the first time — re-running it after you've hand-edited the generated theme is the usual source of lost work, so commit before you run it a second time.
First things to look at, in this order
button and card.vendor/artisanpack-ui/livewire-ui-components/resources/views/components/ — Blade components are thin, readable markup. When a prop isn't documented, the view is the spec.First real use case
Pick a single boring CRUD form and rebuild it with the library: a card wrapping input/select/textarea bound with wire:model, a button for submit, and a toast on success. That exercises the three things you actually need to validate before adopting it broadly: form binding ergonomics, Livewire re-render behavior, and whether your Tailwind build keeps the daisyUI classes.
<x-artisanpack-card>
<x-slot:header>
<h3 class="text-lg font-bold">New Customer</h3>
</x-slot:header>
<x-artisanpack-input label="Name" wire:model="name" />
<x-artisanpack-select label="Plan" wire:model="plan" :options="$plans" />
<x-slot:footer>
<x-artisanpack-button color="primary" wire:click="save" spinner>Save</x-artisanpack-button>
</x-slot:footer>
</x-artisanpack-card>
Optional dependencies are genuinely optional — until a component silently does nothing. Charts need apexcharts, date pickers need flatpickr, and XLSX/PDF export need phpoffice/phpspreadsheet and barryvdh/laravel-dompdf. CSV export works bare. Install the JS deps up front if you plan to use those components at all.
Treat the components as presentational wrappers, not form logic. They pass wire:model through to the underlying input, so your Livewire component keeps validation, authorization, and persistence as normal. The value is consistent markup, spacing, and error-state styling — not abstracted behavior. Keep $rules, $this->validate(), and error display in the Livewire class.
Toast trait for action feedback. Use the provided toast trait from your Livewire component after save(), delete(), etc., rather than hand-rolling flash messages. This is also the seam where ap.livewireUiComponents.toastDispatched fires, so you get analytics for free later:
Action::add('ap.livewireUiComponents.toastDispatched', function (string $type, string $title) {
analytics()->track('toast_shown', compact('type', 'title'));
});
Modals: dispatch to open, bridge for hooks. Modals open through Alpine on the client, so the server has no idea a modal appeared. If you want lifecycle hooks, fire the bridge yourself:
use ArtisanPack\LivewireUiComponents\Support\ModalBridge;
public function confirmDelete(): void
{
ModalBridge::willOpen('confirm-delete');
$this->dispatch('open-modal', id: 'confirm-delete');
}
Do not assume modalWillOpen fires just because a modal opened — it only fires where you call the bridge. Use it for audit logging or "user abandoned the dialog" telemetry, not for required business logic.
Tables: always server-side paginate. Build the headers array in the Livewire class, feed rows from a paginator, and let per-row actions dispatch Livewire methods. Never hand a table a full Eloquent collection with eager-loaded relations — the payload and memory cost is the usual complaint. Export is where this bites hardest: CSV is fine, XLSX/PDF on a 50k-row export will time out. Queue it.
Charts need wire:ignore plus an Alpine update path. ApexCharts owns the DOM node. If Livewire morphs the chart container on re-render, the chart vanishes. Wrap in wire:ignore and push new data via a dispatched browser event or an Alpine component, exactly as you would with any ApexCharts integration.
Theming is a one-time generative step, then token discipline. Run php artisan artisanpack:generate-theme once, commit the output, and from then on style via semantic props (color="primary", color="error") rather than adding Tailwind overrides to individual components. If you find yourself fighting the component with class="bg-blue-600", you've skipped a theme token. The themeColors filter is the escape hatch for ThemeToggle if you need a third theme:
Filter::add('ap.livewireUiComponents.themeColors', function (array $themes) {
$themes['brand'] = ['label' => 'Brand', 'theme' => 'brand', 'class' => ''];
return $themes;
});
Icon aliasing, not icon find-and-replace. If you're migrating from a Font Awesome codebase, don't sed your Blade files — map the names centrally:
Filter::add('ap.livewireUiComponents.iconAlias', fn (string $name) => match ($name) {
'fa-home' => 'o-home',
'fa-user' => 'o-user',
default => $name,
});
Spotlight search as your command palette. The spotlightCommands filter fires in the route handler and receives the authenticated user, which makes it the right place to build permission-aware navigation commands. Keep command generation cheap — this runs per keystroke-adjacent request if you wire it to a live endpoint.
Integrate into your app layout, don't adopt theirs. Use the layout/menu/sidebar components as building blocks inside the layout you already have. Adopting a library-owned layout shell is the hardest thing to unwind later.
Tailwind will purge the package's classes if you don't tell it to scan vendor Blade files. This is the number-one setup failure: components render, but everything looks unstyled, and it looks like a package bug. Add the vendor view path to your Tailwind content (or safelist) config, and re-check this after any Tailwind v3→v4 migration.
The vendor path in the README's JS examples assumes a symlinked install. ../../vendor/artisanpack-ui/... works for a path-repository symlink; a normal Composer install nests differently. If your chart or sparkline Alpine component is "undefined," check the import path resolves before you debug anything else.
componentClasses is opt-in per component; componentAttributes is not. The changelog is explicit that only components routing their class list through $this->getClasses() respect the classes filter. Never build required styling on componentClasses — it will silently not apply to some components. componentAttributes fires on every render and is the safer hook for cross-cutting attributes.
Naming and command prefixes are inconsistent — memorize the two. Components are <x-artisanpack-*>, the installer is livewire-ui-components:install, but the theme generator is artisanpack:generate-theme. And older v0.x code used the doubled artisanpack-artisanpack- prefix; if you're copying snippets from a blog post or older branch, that's why the component isn't found.
Component not found / stale markup. Run php artisan view:clear and confirm the service provider is auto-discovered. Blade component resolution failures after an upgrade are almost always the compiled view cache.
This is a young fork — pin it and read the changelog. It's a fork of MaryUI (acknowledged in the README), 1 star, 0 dependents, and the changelog is granular to the point of 0.4.2 — "various fixes". That tells you the surface is still moving. Pin a minor version, read changelogs before bumping, and test in staging. The v1→v2 jump is documented as fully backwards compatible, which is a good sign, but "backwards compatible" here means component API, not necessarily rendered markup.
The declared license is NOASSERTION while the README and license.md say MIT. For most teams that's fine, but if you need automated license compliance this will flag. Resolve it with your legal/security tooling before it becomes a procurement blocker, and reference the actual license.md file rather than the composer metadata.
Verify the accessibility claims yourself. "Accessibility focused" is credible for a MaryUI-derived library (daisyUI handles focus rings and contrast reasonably), but icon-only buttons and table row actions are where hand-rolled aria-labels go missing. Run one axe pass on your busiest page before you trust it as a selling point to stakeholders.
Publish and override views rather than forking. Components are Blade files; vendor:publish the ones you need to change. Forking the package to tweak a div means you own the merge forever on a library that is actively changing.
Zero dependents plus one star means you are the QA. Budget for writing your own smoke test around the handful of components you actually use — a Livewire render test per component catches the upgrade breakages that the changelog's "various fixes" entries won't.
How can I help you explore Laravel packages today?