laravelcm/livewire-slide-overs
Livewire slide-over drawer panel for Laravel. Open slide-overs via events, stack multiple child components, and preserve state—modal-like behavior inspired by wire-elements/modal, but as a drawer. Supports PHP 8.3+, Laravel 11/12, Livewire 3.4/4.
Installation:
composer require laravelcm/livewire-slide-overs
Ensure your project meets requirements: PHP 8.3+, Laravel 11/12, Livewire 3.4/4.x.
Add the Livewire directive to your layout (e.g., resources/views/layouts/app.blade.php):
@livewire('slide-over-panel')
Create your first slide-over component:
php artisan make:livewire ShoppingCart
Extend SlideOverComponent in the generated class:
use Laravelcm\LivewireSlideOvers\SlideOverComponent;
class ShoppingCart extends SlideOverComponent
{
public function render() { return view('livewire.shopping-cart'); }
}
Trigger the slide-over from a Blade view:
<button wire:click="$dispatch('openPanel', { component: 'shopping-cart' })">
Open Cart
</button>
Replace a traditional modal with a slide-over for a shopping cart or user profile. The package handles animations, stacking, and state management automatically.
Mounting Data: Pass arguments via $dispatch to mount():
<button wire:click="$dispatch('openPanel', {
component: 'edit-user',
arguments: { userId: {{ $user->id }} }
})">Edit</button>
public function mount(int $userId) { $this->user = User::find($userId); }
Dynamic Resizing: Adjust width during runtime:
public function expand() { $this->resizePanel('max-w-5xl'); }
Closing Logic: Use closePanel() with optional events:
public function save() {
$this->closePanelWithEvents(['refreshList']);
}
config/livewire-slide-over.php):
'stack' => true,
<button wire:click="$dispatch('openPanel', { component: 'step-one' })">Step 1</button>
// Inside StepOne component:
public function proceed() {
$this->closePanel()->dispatch('openPanel', ['component' => 'step-two']);
}
$slideOver.open() for immediate feedback:
<button onclick="$slideOver.open('shopping-cart')">Cart</button>
sessionStorage for subsequent opens.public static function panelMaxWidth(): string { return '3xl'; }
public static function closePanelOnEscape(): bool { return false; }
#[On] attributes (Livewire 4+):
use Laravelcm\LivewireSlideOvers\Events\PanelClosed;
#[On('panel.closed')]
public function handlePanelClosed(PanelClosed $event) {
// React to closures
}
Tailwind CSS Setup:
@source to your CSS:
@source "../vendor/laravelcm/livewire-slide-vers/resources/views";
tailwind.config.js:
content: ['./vendor/laravelcm/livewire-slide-overs/resources/views/**/*.blade.php'],
Component Naming:
Shop/Actions/ShoppingCart → 'shop.actions.shopping-cart').-) in component names; use underscores (_) or camelCase.Stacked Panel Quirks:
closePanelOnEscapeIsForceful).overflow: hidden to prevent stacking artifacts.Dynamic Resizing:
max-w-2xl) or JIT values (e.g., max-w-[800px]).Model Binding:
mount() for automatic binding:
public function mount(User $user) { /* ... */ }
Check Console for Errors:
Uncaught ReferenceError: $slideOver is not defined if JS isn’t loaded. Verify include_js in config.Inspect Panel Attributes:
sessionStorage caches panel attributes correctly for instant opens.Stacked Panel Debugging:
x-data to Blade to log panel IDs:
<div x-data="{ panels: [] }" x-on:openPanel="panels.push($event.detail.component)">
{{ json_encode($panels) }}
</div>
Livewire Event Listeners:
#[On] attributes are used in Livewire 4+. For v3, use registerScript:
public function mount() {
$this->registerScript('panelClosed', '$wire.on("panel.closed", () => { /* ... */ })');
}
Custom Animations:
php artisan vendor:publish --tag=livewire-slide-over-assets
resources/js/slide-over.js.Native Dialog Mode:
'native_dialog' => true,
role="dialog").Custom Panel Attributes:
$slideOver.open():
<button onclick="$slideOver.open('panel', {}, { class: 'bg-gray-100' })">Open</button>
Server-Side Logic:
#[On] to react to panel events server-side (e.g., update a parent component’s state when a panel closes).mount(): Fetch data lazily (e.g., in updated() or after panel opens).sessionStorage for instant opens after the first render.How can I help you explore Laravel packages today?