artisanpack-ui / livewire-drag-and-drop
A Livewire and Alpine.js drag-and-drop component with accessibility and Tailwind CSS.
Requires
- php: ^8.2
- illuminate/database: ^10.0 || ^11.0
- illuminate/support: ^10.0 || ^11.0
- livewire/livewire: ^3.0
README
ArtisanPack UI Livewire Drag and Drop is a Laravel package that provides an accessible, customizable drag-and-drop component for Livewire applications. Built with Alpine.js and Sortable.js, this package makes it easy to add sortable lists to your Laravel applications with full keyboard accessibility and screen reader support.
Features
- Accessible Drag and Drop: Full keyboard navigation and screen reader support.
- Livewire Integration: Seamlessly integrates with Livewire for real-time updates.
- Alpine.js Powered: Uses Alpine.js for smooth, reactive UI interactions.
- Eloquent Model Support: Works with any Eloquent model for easy database integration.
- Customizable: Fully customizable appearance using Tailwind CSS.
- Flexible Sorting: Sort any collection of items with customizable order columns.
- Scoped Lists: Optionally scope your sortable lists by any criteria.
Requirements
- PHP 8.2 or higher
- Laravel 10.0 or higher
- Livewire 3.0 or higher
- Tailwind CSS 3.0 or higher
- Alpine.js 3.0 or higher
- Node.js and npm (for asset compilation)
Installation
1. Install the Package
You can install the package via Composer:
composer require artisanpack-ui/livewire-drag-and-drop
2. Publish Assets
After installing the package, you need to publish the assets:
php artisan vendor:publish --tag=artisanpack-ui-livewire-drag-and-drop-assets
This will publish the JavaScript and CSS files to your public directory.
3. Configure Tailwind CSS
Update your tailwind.config.js
file to include the package's components:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./resources/**/*.blade.php',
'./resources/**/*.js',
// Include ArtisanPack UI Livewire Drag and Drop
'./vendor/artisanpack-ui/livewire-drag-and-drop/resources/views/**/*.blade.php',
],
theme: {
extend: {},
},
plugins: [],
}
4. Include the Package's JavaScript and CSS
Add the following to your main layout file:
<!-- In the head section -->
<link rel="stylesheet" href="{{ asset('vendor/artisanpack-ui-livewire-drag-and-drop/css/sortable-package.css') }}">
<!-- Before the closing body tag, after Alpine.js -->
<script src="{{ asset('vendor/artisanpack-ui-livewire-drag-and-drop/js/sortable-plugin.js') }}"></script>
Make sure Alpine.js is loaded before the package's JavaScript.
Prepare Your Model
Your Eloquent model needs to have a column for storing the order. For example:
Schema::create('widgets', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->unsignedInteger('position')->default(0); // The order column
$table->foreignId('dashboard_id')->constrained();
$table->timestamps();
});
Basic Usage
You can use the sortable list component in your Blade templates:
<livewire:artisanpack-ui-livewire-drag-and-drop::sortable-list
:model="'App\\Models\\Widget'"
orderColumn="position"
:scope="['dashboard_id' => $dashboardId]"
>
@foreach ($items as $widget)
<div wire:key="widget-item-{{ $widget->id }}" data-sortable-id="{{ $widget->id }}">
<h3 data-sortable-item-name>{{ $widget->name }}</h3>
<p>{{ $widget->description }}</p>
</div>
@endforeach
</livewire:artisanpack-ui-livewire-drag-and-drop::sortable-list>
Component Properties
model
: The full class name of your Eloquent model (e.g., 'App\Models\Widget')orderColumn
: The name of the column used for ordering (default: 'order')scope
: Optional array of key-value pairs for additional query constraints
Customizing Item Content
You can customize the content of each item by providing a slot for each item in the collection:
<livewire:artisanpack-ui-livewire-drag-and-drop::sortable-list
:model="'App\\Models\\Task'"
orderColumn="position"
>
@foreach ($items as $task)
<div wire:key="task-item-{{ $task->id }}" data-sortable-id="{{ $task->id }}">
<div class="flex items-center">
<span class="text-lg font-semibold" data-sortable-item-name>{{ $task->title }}</span>
<span class="ml-2 text-sm text-gray-500">{{ $task->due_date->format('M d, Y') }}</span>
</div>
<p class="text-gray-700">{{ $task->description }}</p>
<div class="mt-2 flex space-x-2">
@if($task->is_completed)
<span class="px-2 py-1 bg-green-100 text-green-800 rounded-full text-xs">Completed</span>
@else
<span class="px-2 py-1 bg-yellow-100 text-yellow-800 rounded-full text-xs">Pending</span>
@endif
<span class="px-2 py-1 bg-blue-100 text-blue-800 rounded-full text-xs">{{ $task->priority }}</span>
</div>
</div>
@endforeach
</livewire:artisanpack-ui-livewire-drag-and-drop::sortable-list>
Accessibility Features
The component includes several accessibility features:
- Keyboard navigation (Tab to focus, Space/Enter to grab, arrow keys to move, Space/Enter to drop)
- ARIA attributes for screen readers
- Live announcements of drag-and-drop actions
- Alternative "Up" and "Down" buttons for keyboard-only users
Events
The component dispatches a Livewire event when items are reordered:
// Listen for the itemsReordered event in your Livewire component
$this->on('itemsReordered', function () {
// Do something after items are reordered
$this->dispatch('notify', 'Items reordered successfully!');
});
Documentation
For more detailed documentation, please visit the following resources:
Contributing
As an open source project, this package is open to contributions from anyone. Please read through the contributing guidelines to learn more about how you can contribute to this project.
License
The ArtisanPack UI Livewire Drag and Drop package is open-sourced software licensed under the MIT license.