alessandro-nuunes / filament-kanban
Kanban board pages for Filament v5 panels.
Package info
github.com/alessandronuunes/filament-kanban
pkg:composer/alessandro-nuunes/filament-kanban
Fund package maintenance!
v1.0.0
2026-03-28 12:33 UTC
Requires
- php: ^8.2|^8.3|^8.4
- filament/filament: ^5.0
- illuminate/contracts: ^11.0|^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- pestphp/pest-plugin-livewire: ^3.0
README
Kanban board pages for Filament v5 panels (PHP 8.2+ / Laravel 11–12).
First Kanban plugin built natively for Filament v5.
Drag-and-drop, status transitions, edit modal, Enum integration, dark mode.
Requirements
- PHP 8.2+
- Laravel 11.x or 12.x
- Filament 5.x
Installation
composer require alessandro-nuunes/filament-kanban
Publish config and translations:
php artisan filament-kanban:install
Add the @source to your Filament theme CSS so Tailwind picks up the plugin classes:
/* resources/css/filament/admin/theme.css */ /* via Composer (production) */ @source '../../../../vendor/alessandro-nuunes/filament-kanban/resources/views/**/*'; /* via local packages/ (development) */ @source '../../../../packages/filament-kanban/resources/views/**/*';
Then rebuild assets:
npm run build
Quick Start
1. Generate a Kanban page
php artisan make:filament-kanban TicketsKanban --resource=TaskResource --model=Task --panel=admin
This creates app/Filament/Admin/Resources/Tasks/Pages/TicketsKanban.php.
2. Register it in your Resource
// TaskResource.php public static function getPages(): array { return [ 'index' => Pages\ListTasks::route('/'), 'kanban' => Pages\TicketsKanban::route('/kanban'), 'view' => Pages\ViewTask::route('/{record}'), ]; }
3. Add your Enum (optional but recommended)
use AlessandroNuunes\FilamentKanban\Contracts\HasKanbanStatuses; use AlessandroNuunes\FilamentKanban\Concerns\InteractsWithKanbanStatuses; use Filament\Support\Contracts\HasColor; use Filament\Support\Contracts\HasLabel; enum TaskStatus: string implements HasKanbanStatuses, HasColor, HasLabel { use InteractsWithKanbanStatuses; case Pending = 'pending'; case InProgress = 'in_progress'; case Completed = 'completed'; case Cancelled = 'cancelled'; // Only show these 3 on the board public static function kanbanCases(): array { return [self::Pending, self::InProgress, self::Completed]; } public function getLabel(): ?string { return match ($this) { self::Pending => 'Pending', self::InProgress => 'In Progress', self::Completed => 'Completed', self::Cancelled => 'Cancelled', }; } public function getColor(): string|array|null { return match ($this) { self::Pending => 'warning', self::InProgress => 'info', self::Completed => 'success', self::Cancelled => 'gray', }; } }
4. Point the board to your Enum
class TicketsKanban extends KanbanBoard { protected static string $resource = TaskResource::class; protected static string $model = Task::class; protected static ?string $statusEnum = TaskStatus::class; protected static string $recordStatusAttribute = 'status'; protected static string $recordTitleAttribute = 'protocol'; protected function onStatusChanged( int|string $recordId, string $newStatus, array $fromOrderedIds, array $toOrderedIds, ): void { Task::find($recordId)?->update(['status' => $newStatus]); } }
Configuration
config/filament-kanban.php
return [ // 'record' = calls canMoveRecord() on the page // 'policy' = calls $policy->update($user, $record) 'authorization_mode' => 'record', 'default_status_attribute' => 'status', 'default_title_attribute' => 'title', // Max height of each column's scroll area 'board_max_height' => '75vh', // Enable the inline edit modal (click on card) 'enable_edit_modal' => true, ];
All overridable methods
| Method | Description |
|---|---|
statuses(): Collection |
Manual statuses when not using an Enum |
records(): Collection |
Filter/scope which records appear |
onStatusChanged(...) |
Persist status change + side-effects |
onSortChanged(...) |
Persist reordering within a column |
canMoveRecord(Model, from, to): bool |
Block specific moves |
allowedTransitions(): ?array |
Restrict status-to-status transitions |
mutateRecordDataForCard(array, Model) |
Customize data passed to card view |
getEditModalFormSchema(?id): array |
Define edit modal form fields |
editRecord(id, data, state): void |
Handle edit modal save |
getSortColumn(): ?string |
Column name for persistent ordering |
shouldPersistSorting(): bool |
Whether to persist column sort order |
Status transitions
protected function allowedTransitions(): ?array { return [ 'pending' => ['in_progress', 'cancelled'], 'in_progress' => ['completed', 'pending'], // null or missing key = no restriction from that status ]; }
Manual statuses (no Enum)
protected function statuses(): Collection { return collect([ ['id' => 'todo', 'title' => 'To Do', 'color' => 'gray'], ['id' => 'in_progress', 'title' => 'In Progress', 'color' => 'info'], ['id' => 'done', 'title' => 'Done', 'color' => 'success'], ]); }
Events
Listen to these events in your application:
use AlessandroNuunes\FilamentKanban\Events\KanbanRecordStatusChanging; use AlessandroNuunes\FilamentKanban\Events\KanbanRecordStatusChanged; use AlessandroNuunes\FilamentKanban\Events\KanbanRecordSortingChanged; Event::listen(KanbanRecordStatusChanged::class, function ($event) { // $event->userId, recordId, fromStatus, toStatus, fromOrderedIds, toOrderedIds });
Customizing views
Publish all views:
php artisan vendor:publish --tag="filament-kanban-views"
Or override per board:
protected static string $boardView = 'my-package::kanban-board'; protected static string $columnView = 'my-package::kanban-column'; protected static string $cardView = 'my-package::kanban-card'; protected static string $emptyView = 'my-package::kanban-empty'; protected static string $scriptsView = 'my-package::kanban-scripts';
Theme (required)
/* production */ @source '../../../../vendor/alessandro-nuunes/filament-kanban/resources/views/**/*'; /* local development */ @source '../../../../packages/filament-kanban/resources/views/**/*';
License
MIT — see LICENSE.md.
Author
Alessandro Nuunes — GitHub