modus-digital/livewire-datatables

Reusable Laravel Livewire datatable for the TALL stack—Tailwind-styled, concern-driven (columns, filters, sorting, pagination, row actions), fully testable with Pest & Larastan-ready.

v1.0 2025-06-03 14:28 UTC

README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

A reusable, highly-customizable Livewire Datatable component for the TALL stack (Tailwind CSS, Alpine.js, Laravel, Livewire). Built with modularity, testability, and developer experience in mind.

Features

  • 🎨 Beautiful Tailwind CSS styling with dark mode support
  • 🔍 Global search with debounced input (300ms)
  • 🗂️ Advanced filtering with multiple filter types
  • 📊 Column sorting with visual indicators
  • 📄 Pagination with customizable page sizes
  • Row selection with bulk actions
  • 🔧 Highly customizable with traits and concerns
  • 🧪 Fully tested with Pest 3
  • 📱 Responsive design for all screen sizes
  • Accessibility features built-in

Installation

You can install the package via composer:

composer require modus-digital/livewire-datatables

Optionally, you can publish the views using:

php artisan vendor:publish --tag="livewire-datatables-views"

Quick Start

1. Create a Table Component

<?php

use App\Models\User;
use ModusDigital\LivewireDatatables\Table;
use ModusDigital\LivewireDatatables\Columns\Column;
use ModusDigital\LivewireDatatables\Filters\SelectFilter;

class UsersTable extends Table
{
    protected string $model = User::class;

    protected function columns(): array
    {
        return [
            Column::make('Name')
                ->field('name')
                ->sortable()
                ->searchable(),

            Column::make('Email')
                ->field('email')
                ->sortable()
                ->searchable(),

            Column::make('Role')
                ->relationship('profile', 'role')
                ->sortable(),

            Column::make('Status')
                ->field('status')
                ->format(fn($value) => ucfirst($value)),
        ];
    }

    protected function filters(): array
    {
        return [
            SelectFilter::make('Status')->options([
                'active' => 'Active',
                'inactive' => 'Inactive',
                'banned' => 'Banned',
            ]),
        ];
    }
}

2. Use in Your Blade Template

<div>
    <livewire:users-table />
</div>

Advanced Usage

Column Configuration

Column::make('Avatar')
    ->field('avatar_url')
    ->view('components.avatar') // Custom view
    ->attributes(['header_class' => 'w-16']),

Column::make('Created')
    ->field('created_at')
    ->sortable()
    ->format(fn($value) => $value->diffForHumans()),

Column::make('Actions')
    ->view('components.user-actions')
    ->attributes(['cell_class' => 'text-right']),

Row Selection & Bulk Actions

class UsersTable extends Table
{
    public bool $enableRowSelection = true;

    protected function bulkActions(): array
    {
        return [
            [
                'name' => 'Delete Selected',
                'key' => 'delete',
                'class' => 'bg-red-600 hover:bg-red-700',
            ],
            [
                'name' => 'Export Selected',
                'key' => 'export',
                'class' => 'bg-green-600 hover:bg-green-700',
            ],
        ];
    }

    public function bulkActionDelete($rows)
    {
        $rows->each->delete();
        session()->flash('message', 'Selected users deleted successfully.');
    }

    public function bulkActionExport($rows)
    {
        // Export logic here
    }
}

Row Actions

protected function rowActions(): array
{
    return [
        [
            'name' => 'Edit',
            'key' => 'edit',
            'icon' => '<path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/>',
        ],
        [
            'name' => 'Delete',
            'key' => 'delete',
            'class' => 'text-red-600 hover:text-red-900',
        ],
    ];
}

public function rowActionEdit($row)
{
    return redirect()->route('users.edit', $row);
}

public function rowActionDelete($row)
{
    $row->delete();
    session()->flash('message', 'User deleted successfully.');
}

Global Actions

protected function globalActions(): array
{
    return [
        [
            'name' => 'Add User',
            'key' => 'create',
            'label' => '+ Add User',
            'class' => 'bg-orange-600 hover:bg-orange-700',
        ],
    ];
}

public function globalAction($action)
{
    if ($action === 'create') {
        return redirect()->route('users.create');
    }
}

Custom Empty State

public string $emptyStateTitle = 'No users found';
public string $emptyStateDescription = 'Get started by creating your first user.';

Pagination Configuration

public int $perPage = 25;
public array $perPageOptions = [10, 25, 50, 100];
public bool $showPerPageSelector = true;

Customization

Publishing Views

To customize the table appearance, publish the views:

php artisan vendor:publish --tag="livewire-datatables-views"

This will publish all Blade templates to resources/views/vendor/livewire-datatables/.

Styling

The package uses Tailwind CSS classes exclusively. You can:

  1. Override CSS classes by modifying the published views
  2. Add custom attributes to columns using the attributes() method
  3. Use custom views for specific columns with the view() method

Dark Mode

Dark mode is supported out of the box using Tailwind's dark: variants. Ensure your project has dark mode configured in tailwind.config.js:

module.exports = {
    darkMode: 'class', // or 'media'
    // ... rest of config
}

Testing

The package includes comprehensive tests using Pest 3:

composer test

All traits are individually tested with feature tests covering:

  • Column functionality
  • Filtering and search
  • Sorting mechanisms
  • Pagination
  • Row selection
  • Bulk actions

Architecture

The package follows a modular architecture using traits:

  • HasColumns - Column management and rendering
  • HasFilters - Filter functionality
  • HasPagination - Pagination configuration
  • HasSorting - Sorting logic
  • HasRowSelection - Row selection and bulk actions
  • HasRowActions - Individual row actions

Each trait is under 150 lines of code and fully unit tested.

Requirements

  • PHP 8.3+
  • Laravel 10.0+ | 11.0+ | 12.0+
  • Livewire 3.0+
  • Tailwind CSS 3.0+
  • Alpine.js 3.0+

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.