Weave Code
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

Filament Kanban Laravel Package

alessandro-nuunes/filament-kanban

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Installation:

    composer require alessandro-nuunes/filament-kanban
    php artisan filament-kanban:install
    

    Add @source directive to resources/css/filament/admin/theme.css (as shown in README) and rebuild assets.

  2. Generate a Kanban Page:

    php artisan make:filament-kanban TicketsKanban --resource=TaskResource --model=Task --panel=admin
    

    This creates a scaffolded Kanban page in app/Filament/Admin/Resources/Tasks/Pages/TicketsKanban.php.

  3. Register the Page: Add the generated page to your resource’s getPages() method:

    public static function getPages(): array {
        return [
            'index'  => Pages\ListTasks::route('/'),
            'kanban' => Pages\TicketsKanban::route('/kanban'),
            'view'   => Pages\ViewTask::route('/{record}'),
        ];
    }
    
  4. First Run: Visit /admin/tasks/kanban in your Filament panel. The board will render empty unless you configure columns and data.


First Use Case: Displaying Tasks by Status

  1. Define an Enum (if not already present):

    // app/Models/Task.php
    use Filament\Support\Enums\Status;
    
    public static function getStatusOptions(): array {
        return Status::options([
            'todo'    => 'To Do',
            'in-progress' => 'In Progress',
            'done'   => 'Done',
        ]);
    }
    
  2. Configure the Kanban Page: Override getColumns() and getRecords() in TicketsKanban.php:

    public function getColumns(): array {
        return [
            'todo' => 'To Do',
            'in-progress' => 'In Progress',
            'done' => 'Done',
        ];
    }
    
    public function getRecords(): array {
        return Task::query()
            ->orderBy('status')
            ->get()
            ->toArray();
    }
    
  3. Map Records to Columns: Override getColumnForRecord() to assign records to columns:

    public function getColumnForRecord(Task $record): string {
        return $record->status;
    }
    

Now, tasks will appear in their respective columns based on the status field.


Implementation Patterns

Core Workflows

1. Dynamic Column Configuration

Use getColumns() to define columns dynamically (e.g., fetch from a database or API):

public function getColumns(): array {
    return Cache::remember('kanban_columns', now()->addHours(1), function () {
        return Status::getOptions();
    });
}

2. Customizing Card Rendering

Override getCard() to modify how records appear as cards:

public function getCard(Task $record): array {
    return [
        'title' => $record->title,
        'description' => $record->description,
        'avatar' => $record->assigned_user->avatar,
        'badge' => $record->priority,
        'actions' => [
            Action::make('edit')
                ->url(fn (Task $record) => $this->getResource()::getUrl('edit', ['record' => $record])),
        ],
    ];
}

3. Handling Drag-and-Drop Updates

Listen for column changes via getColumnChanged():

protected function getColumnChanged(): string {
    return 'status';
}

protected function handleColumnChanged(Task $record, string $newColumn): void {
    $record->update(['status' => $newColumn]);
}

4. Integration with Filament Actions

Add Filament actions (e.g., bulk actions) to the Kanban page:

public function getHeaderActions(): array {
    return [
        Action::make('create')
            ->url(fn () => $this->getResource()::getUrl('create')),
        Action::make('export')
            ->icon('heroicon-o-arrow-down-tray')
            ->url(fn () => route('filament.admin.tasks.export')),
    ];
}

5. Filtering Records

Use Filament’s built-in filtering or add custom logic:

public function getRecords(): array {
    return Task::query()
        ->when($this->getFilters(), fn ($query) => $this->applyFilters($query))
        ->get()
        ->toArray();
}

Integration Tips

With Filament Resources

  • Reuse Resource Logic: Leverage the resource’s getTableRecords() or getTableColumns() for consistency.
  • Shared Filters: Sync filters between the list and Kanban pages:
    public function getFilters(): array {
        return $this->getResource()->getTableFilters();
    }
    

With Custom Models

  • Polymorphic Relationships: Handle records with shared status fields:
    public function getColumnForRecord($record): string {
        return $record->status_column ?? 'default';
    }
    

With API Data

  • Remote Data Fetching: Override getRecords() to fetch from an external API:
    public function getRecords(): array {
        return Http::get('https://api.example.com/tasks')->json();
    }
    

With Dark Mode

  • Tailwind Classes: Ensure your custom CSS uses dark: variants for consistency:
    .kanban-card {
        @apply bg-white dark:bg-gray-800;
    }
    

Gotchas and Tips

Pitfalls

  1. Missing @source Directive:

    • Symptom: Kanban styles or assets fail to load.
    • Fix: Ensure @source is added to theme.css and run npm run build.
  2. Column Assignment Conflicts:

    • Symptom: Records don’t appear in any column.
    • Fix: Verify getColumnForRecord() returns a key matching getColumns().
    • Debug: Add dd($record->status) to check the status value.
  3. Drag-and-Drop Not Working:

    • Symptom: Cards can’t be moved between columns.
    • Fix: Ensure getColumnChanged() returns the correct field name (e.g., 'status').
    • Debug: Check browser console for JS errors (e.g., missing Alpine.js or Tailwind).
  4. Enum Mismatch:

    • Symptom: Columns render but records don’t populate.
    • Fix: Ensure the model’s getStatusOptions() matches the Kanban page’s getColumns().
  5. Caching Issues:

    • Symptom: Changes to columns or records aren’t reflected.
    • Fix: Clear Filament’s cache:
      php artisan filament:cache-reset
      

Debugging Tips

  1. Log Column Assignments: Add temporary logging in getColumnForRecord():

    public function getColumnForRecord(Task $record): string {
        \Log::debug('Assigning record ID ' . $record->id . ' to column: ' . $record->status);
        return $record->status;
    }
    
  2. Inspect API Requests: Use Laravel’s debug bar or Chrome DevTools to verify data fetched in getRecords().

  3. Check Tailwind Conflicts: If styles break, inspect the generated HTML to ensure no duplicate or conflicting classes exist.


Configuration Quirks

  1. Default Column: If a record’s column isn’t found, it defaults to 'default'. Override getDefaultColumn():

    public function getDefaultColumn(): string {
        return 'todo';
    }
    
  2. Empty State: Customize the empty state message:

    public function getEmptyState(): string {
        return 'No tasks found. Create one to get started!';
    }
    
  3. Card Height: Adjust card height via Tailwind classes in getCard():

    public function getCard(Task $record): array {
        return [
            'title' => $record->title,
            'classes' => 'h-32', // Custom height
        ];
    }
    

Extension Points

  1. Custom Card Components: Replace the default card view by publishing and overriding:

    php artisan vendor:publish --tag=filament-kanban-views
    

    Then modify resources/views/kanban/card.blade.php.

  2. Column Headers: Customize column headers by overriding getColumnHeader():

    public function getColumnHeader(string $column): array {
        return [
            'title' => ucfirst($column),
            'icon' => match ($column) {
                'done' => 'heroicon-o-check-circle',
                default => 'heroicon-o-rectangle-stack',
            },
        ];
    }
    
  3. Event Listeners: Listen for column changes globally by registering a listener for FilamentKanban\Events\ColumnChanged:

    use FilamentK
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope