Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

X Livewire Laravel Package

erickcomp/x-livewire

A Laravel package that extends Livewire with extra utilities and helpers for building dynamic, reactive interfaces. It aims to simplify common component workflows, though adoption is minimal and documentation is limited, so evaluate its fit carefully before using it in production.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before you type composer require: this is a v1.0.0 with no README and no test suite — both are listed as open TODOs by the author. There is no documented API surface. Your first "getting started" step is therefore reading the source, not following a tutorial. Budget half a day.

1. Read the package before installing it. The whole evaluation hinges on three files:

  • vendor/erickcomp/x-livewire/composer.json → require constraints (PHP floor, illuminate/* range, livewire/livewire range), and extra.laravel.providers.
  • src/ → the service provider, plus any trait, base class, or Blade:: macro registration. This is your entire documentation.
  • Any resources/views/ → tells you what the package expects to render.

Diff what it registers globally (providers, facades, Blade directives) before letting it boot in an app you care about.

2. Install and pin exactly.

composer require erickcomp/x-livewire:1.0.0
php artisan view:clear && php artisan optimize:clear

Do not use ^1.0. There is no changelog and no tests, so a floating constraint buys you nothing but surprise.

3. Confirm it actually booted. Blade component features are registered at boot/compile time, so a silent no-op looks identical to a working install until you render something:

// tinker
app('blade.compiler');                     // inspect for macros
Blade::getClassComponentAliases();         // any new aliases?

Then diff php artisan about (providers section) against the pre-install output.

4. First use case — the one that justifies the package. The stated purpose is "Normal Blade Component features to Livewire components." The concrete payoff is a Livewire component that accepts slot content and an attribute bag, so this:

<livewire:ui.card class="mt-4" wire:key="card-1">
    <x-slot:header>Recent orders</x-slot:header>
    @foreach ($orders as $order) ... @endforeach
</livewire:ui.card>

…renders like a normal <x-card>, instead of forcing you into @include + $slot plumbing or passing pre-rendered HTML strings. Inside the Livewire view you'd expect $slot, $header, and $attributes to be available.

Build a 15-line throwaway component that exercises exactly that, on a branch, before you commit to anything. If that one case doesn't work as described, stop — you have your answer for the price of an hour.


Implementation Patterns

Wrap it. Don't scatter it. This is the highest-leverage pattern given the package's maturity. Put every call site behind one class you own:

// app/Livewire/Concerns/SupportsBladeSlots.php
// or app/Livewire/SlottedComponent.php extending the package's class/trait

Then every component in your app extends your base. When (not if) a 1.x minor changes behavior, you patch one file instead of 40 views. It also gives you a clean exit ramp: the replacement is a base class you already control.

Attribute forwarding is the workhorse. The day-to-day value is in the view:

{{-- resources/views/livewire/ui/card.blade.php --}}
<div {{ $attributes->class(['rounded-lg border bg-white p-4']) }}>
    @isset($header)
        <header class="mb-2 font-semibold">{{ $header }}</header>
    @endisset
    {{ $slot }}
</div>

->class() and ->merge() compose caller-supplied classes with defaults, which is exactly the ergonomics people miss when they hand-roll Livewire layout components. Use $slot->isEmpty() when the presence of body content should change the wrapper markup.

Named slots for layout regions. Treat a Livewire component as a shell — header / body / footer / actions — rather than passing rendered strings through public properties. Rendered-HTML properties are un-escaped, un-testable, and defeat wire: directives inside them.

Compose with your existing Blade library, don't replace it. The sane split:

  • <x-*> for pure presentational markup (buttons, badges, inputs).
  • <livewire:*> for anything with state.
  • The package's job is making the second behave like the first at the boundary.

Keep your component namespace distinct (<livewire:ui.*>) so a future removal of the package is a grep, not an archaeology project.

Testing pattern. Livewire's test helpers don't know about slots, so assert the rendered HTML:

Livewire::test(Card::class, ['orders' => $orders])
    ->assertSee('Recent orders')
    ->assertSeeHtml('class="rounded-lg');   // proves the attribute bag merged

Livewire::test(Card::class)
    ->assertDontSee('mb-2 font-semibold');  // header block absent when slot unfilled

Write these for every slotted component you build. The package has no tests, so your suite is the only executable specification of the behavior you're depending on — and it doubles as the regression check on your next Laravel upgrade.

Migration path from @include. If you already have layout partials taking $title/$content variables, slotted Livewire components are a genuine readability win:

{{-- before --}}
@include('partials.card', ['title' => 'Recent orders', 'content' => $html])

{{-- after --}}
<livewire:ui.card>
    <x-slot:header>Recent orders</x-slot:header>
    @foreach ($orders as $order) ... @endforeach
</livewire:ui.card>

Convert one, test it, then batch the rest. Don't rewrite the whole view layer against an unverified package.


Gotchas and Tips

Slot content is parent-scoped — expect staleness. Slot markup is evaluated where the <livewire:...> tag is written. When the child updates via wire:model, the parent-supplied slot is not necessarily re-rendered. If you see stale rows inside a card, this is why. Fixes: move the loop inside the child (pass data, not markup), or key the component with wire:key and force a parent refresh. Verify actual behavior in your Livewire major — v2 and v3 differ meaningfully here.

wire: attributes on the component tag. Livewire intercepts attributes on <livewire:...> and applies its own handling (wire:key, wire:poll, etc.) before/independently of any attribute bag the package constructs. Test a tag carrying both a plain class and a wire: directive; ordering surprises are the most likely integration bug.

Blade features are compile-time; Livewire renders at runtime. Anything the package registers as a Blade directive, macro, or component alias is baked into compiled views. After install or upgrade, always:

php artisan view:clear
php artisan optimize:clear

A stale storage/framework/views is the single most common cause of "I installed it and nothing happened," and it wastes an afternoon because the code looks correct.

Debugging the attribute bag and slots.

@dump($attributes ?? null)
@dump(isset($slot) ? $slot->toHtml() : 'NO SLOT')

If $slot is undefined, the package's plumbing isn't reaching your view — check the base class/trait is actually applied to the component and that the provider booted. Also inspect Blade::getClassComponentAliases() and app('blade.compiler')->getCustomDirectives() to see what was actually registered versus what you assumed.

Version constraints are the real gate. Confirm composer.json admits both your current and next planned Laravel major, and that it names a livewire/livewire range at all. A package that doesn't constrain Livewire is one that silently broke on the v2→v3 boundary. If it pins a major you're leaving, the integration is a dead end regardless of code quality.

Global registration collisions. Watch for a facade alias, global helper function, or config key namespace that collides with app code. Check whether it publishes config (php artisan vendor:publish --provider=...) — if it does, publish and commit it, otherwise you're depending on package defaults that can change under you.

Full-page components and layouts. Slots in a layout file are a different code path from slots in a nested component. Test the full-page route case separately; it's where Blade/Livewire interaction is thinnest.

Exit plan, written down. Because the integration sits behind one base class, removal is: re-implement slot/attribute handling in your own base (or use Livewire's native attribute merging if your version covers it), delete the dependency, run the suite. Keep a short internal note next to that base class capturing what the package actually does — it's your substitute for upstream documentation and the only thing a new engineer will have.

Re-review trigger. When the README and test TODOs close, re-read src/ against your wrapper and decide whether the package now earns its keep — or whether your base class has quietly grown to replace it.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console