tables

FilamentPHP Tables Generation Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "tables" with this command: npx skills add mwguerra/claude-code-plugins/mwguerra-claude-code-plugins-tables

FilamentPHP Tables Generation Skill

Overview

This skill generates FilamentPHP v4 table configurations with columns, filters, actions, and bulk operations following official documentation patterns.

Documentation Reference

CRITICAL: Before generating tables, read:

  • /home/mwguerra/projects/mwguerra/claude-code-plugins/filament-specialist/skills/docs/references/tables/

  • /home/mwguerra/projects/mwguerra/claude-code-plugins/filament-specialist/skills/docs/references/tables/02-columns/

  • /home/mwguerra/projects/mwguerra/claude-code-plugins/filament-specialist/skills/docs/references/tables/03-filters/

Workflow

Step 1: Analyze Requirements

Identify:

  • Columns to display

  • Searchable fields

  • Sortable fields

  • Filter requirements

  • Row actions

  • Bulk actions

  • Relationships to display

Step 2: Read Documentation

Navigate to table documentation and extract:

  • Column class names and options

  • Filter configurations

  • Action patterns

  • Performance considerations

Step 3: Generate Table

Build table configuration:

use Filament\Tables; use Filament\Tables\Table;

public static function table(Table $table): Table { return $table ->columns([ // Columns ]) ->filters([ // Filters ]) ->actions([ // Row actions ]) ->bulkActions([ // Bulk actions ]); }

Column Types Reference

Text Column

// Basic text Tables\Columns\TextColumn::make('name') ->searchable() ->sortable();

// With limit and tooltip Tables\Columns\TextColumn::make('description') ->limit(50) ->tooltip(fn ($record): string => $record->description);

// Formatted Tables\Columns\TextColumn::make('price') ->money('usd') ->sortable();

// Date formatting Tables\Columns\TextColumn::make('created_at') ->dateTime('M j, Y H:i') ->sortable() ->since(); // Shows "2 hours ago"

// Copyable Tables\Columns\TextColumn::make('uuid') ->copyable() ->copyMessage('UUID copied!') ->copyMessageDuration(1500);

// With color Tables\Columns\TextColumn::make('status') ->color(fn (string $state): string => match ($state) { 'draft' => 'gray', 'reviewing' => 'warning', 'published' => 'success', default => 'gray', });

// HTML content Tables\Columns\TextColumn::make('content') ->html() ->wrap();

// Word/character count Tables\Columns\TextColumn::make('bio') ->words(10);

// List values (array) Tables\Columns\TextColumn::make('tags') ->listWithLineBreaks() ->bulleted();

Icon Column

// Boolean icon Tables\Columns\IconColumn::make('is_active') ->boolean();

// Custom icons Tables\Columns\IconColumn::make('status') ->icon(fn (string $state): string => match ($state) { 'draft' => 'heroicon-o-pencil', 'reviewing' => 'heroicon-o-clock', 'published' => 'heroicon-o-check-circle', }) ->color(fn (string $state): string => match ($state) { 'draft' => 'info', 'reviewing' => 'warning', 'published' => 'success', default => 'gray', });

Image Column

// Basic image Tables\Columns\ImageColumn::make('avatar') ->circular() ->size(40);

// Multiple images (stacked) Tables\Columns\ImageColumn::make('images') ->circular() ->stacked() ->limit(3) ->limitedRemainingText();

// With default Tables\Columns\ImageColumn::make('logo') ->defaultImageUrl(url('/images/default-logo.png')) ->square() ->size(60);

Badge Column

Tables\Columns\BadgeColumn::make('status') ->colors([ 'danger' => 'draft', 'warning' => 'reviewing', 'success' => 'published', ]) ->icons([ 'heroicon-o-pencil' => 'draft', 'heroicon-o-clock' => 'reviewing', 'heroicon-o-check' => 'published', ]);

// Or with closure Tables\Columns\BadgeColumn::make('priority') ->color(fn (string $state): string => match ($state) { 'low' => 'gray', 'medium' => 'warning', 'high' => 'danger', });

Color Column

Tables\Columns\ColorColumn::make('color') ->copyable() ->copyMessage('Color code copied');

Toggle Column

// Editable inline toggle Tables\Columns\ToggleColumn::make('is_active') ->onColor('success') ->offColor('danger') ->afterStateUpdated(fn () => Notification::make() ->title('Status updated') ->success() ->send() );

Select Column

// Editable inline select Tables\Columns\SelectColumn::make('status') ->options([ 'draft' => 'Draft', 'published' => 'Published', ]);

Text Input Column

// Editable inline text Tables\Columns\TextInputColumn::make('sort_order') ->rules(['required', 'numeric']);

Checkbox Column

// Editable inline checkbox Tables\Columns\CheckboxColumn::make('is_featured');

Relationship Columns

// BelongsTo Tables\Columns\TextColumn::make('author.name') ->label('Author') ->searchable() ->sortable();

// HasMany count Tables\Columns\TextColumn::make('comments_count') ->counts('comments') ->label('Comments') ->sortable();

// HasMany sum Tables\Columns\TextColumn::make('items_sum_quantity') ->sum('items', 'quantity') ->label('Total Quantity');

// BelongsToMany list Tables\Columns\TextColumn::make('tags.name') ->badge() ->separator(',');

View Column (Custom)

Tables\Columns\ViewColumn::make('custom') ->view('filament.tables.columns.custom-column');

Column Modifiers

Tables\Columns\TextColumn::make('name') // Search ->searchable() ->searchable(isIndividual: true)

// Sort
->sortable()
->sortable(['first_name', 'last_name'])

// Visibility
->toggleable()
->toggleable(isToggledHiddenByDefault: true)
->visible(fn (): bool => auth()->user()->isAdmin())
->hidden(fn ($record): bool => $record->is_private)

// Sizing
->grow(false)
->width('200px')
->alignCenter()
->alignEnd()

// Styling
->weight(FontWeight::Bold)
->size(TextColumn\TextColumnSize::Large)
->color('primary')
->extraAttributes(['class' => 'custom-class']);

Filters Reference

Select Filter

Tables\Filters\SelectFilter::make('status') ->options([ 'draft' => 'Draft', 'reviewing' => 'Reviewing', 'published' => 'Published', ]);

// Multiple selection Tables\Filters\SelectFilter::make('status') ->multiple() ->options([ 'draft' => 'Draft', 'published' => 'Published', ]);

// Relationship filter Tables\Filters\SelectFilter::make('author') ->relationship('author', 'name') ->searchable() ->preload();

Ternary Filter (Boolean)

Tables\Filters\TernaryFilter::make('is_active') ->label('Active') ->boolean() ->trueLabel('Active only') ->falseLabel('Inactive only') ->native(false);

Date Filter

Tables\Filters\Filter::make('created_at') ->form([ Forms\Components\DatePicker::make('created_from'), Forms\Components\DatePicker::make('created_until'), ]) ->query(function (Builder $query, array $data): Builder { return $query ->when( $data['created_from'], fn (Builder $query, $date): Builder => $query->whereDate('created_at', '>=', $date), ) ->when( $data['created_until'], fn (Builder $query, $date): Builder => $query->whereDate('created_at', '<=', $date), ); }) ->indicateUsing(function (array $data): array { $indicators = []; if ($data['created_from'] ?? null) { $indicators['created_from'] = 'From ' . Carbon::parse($data['created_from'])->toFormattedDateString(); } if ($data['created_until'] ?? null) { $indicators['created_until'] = 'Until ' . Carbon::parse($data['created_until'])->toFormattedDateString(); } return $indicators; });

Trashed Filter (Soft Deletes)

Tables\Filters\TrashedFilter::make();

Query Builder Filter

Tables\Filters\QueryBuilder::make() ->constraints([ Tables\Filters\QueryBuilder\Constraints\TextConstraint::make('name'), Tables\Filters\QueryBuilder\Constraints\NumberConstraint::make('price'), Tables\Filters\QueryBuilder\Constraints\DateConstraint::make('created_at'), Tables\Filters\QueryBuilder\Constraints\RelationshipConstraint::make('author') ->icon('heroicon-o-user') ->multiple(), ]);

Actions Reference

Row Actions

->actions([ Tables\Actions\ViewAction::make(), Tables\Actions\EditAction::make(), Tables\Actions\DeleteAction::make() ->requiresConfirmation(),

// Custom action
Tables\Actions\Action::make('publish')
    ->icon('heroicon-o-check')
    ->color('success')
    ->requiresConfirmation()
    ->action(fn (Model $record) => $record->publish())
    ->visible(fn (Model $record): bool => $record->status === 'draft'),

// Action with modal form
Tables\Actions\Action::make('send_email')
    ->icon('heroicon-o-envelope')
    ->form([
        Forms\Components\TextInput::make('subject')
            ->required(),
        Forms\Components\RichEditor::make('body')
            ->required(),
    ])
    ->action(function (Model $record, array $data): void {
        Mail::to($record->email)->send(new CustomEmail($data));
    }),

// Grouped actions
Tables\Actions\ActionGroup::make([
    Tables\Actions\ViewAction::make(),
    Tables\Actions\EditAction::make(),
    Tables\Actions\DeleteAction::make(),
])->dropdown(),

// Replicate action
Tables\Actions\ReplicateAction::make()
    ->excludeAttributes(['slug', 'published_at'])
    ->beforeReplicaSaved(function (Model $replica): void {
        $replica->name = $replica->name . ' (Copy)';
    }),

]);

Bulk Actions

->bulkActions([ Tables\Actions\BulkActionGroup::make([ Tables\Actions\DeleteBulkAction::make(), Tables\Actions\ForceDeleteBulkAction::make(), Tables\Actions\RestoreBulkAction::make(),

    // Custom bulk action
    Tables\Actions\BulkAction::make('publish')
        ->icon('heroicon-o-check')
        ->requiresConfirmation()
        ->action(fn (Collection $records) => $records->each->publish())
        ->deselectRecordsAfterCompletion(),

    // Export bulk action
    Tables\Actions\BulkAction::make('export')
        ->icon('heroicon-o-arrow-down-tray')
        ->action(fn (Collection $records) => static::export($records)),
]),

]);

Header Actions

->headerActions([ Tables\Actions\CreateAction::make(), Tables\Actions\AttachAction::make() ->preloadRecordSelect(),

// Import action
Tables\Actions\Action::make('import')
    ->icon('heroicon-o-arrow-up-tray')
    ->form([
        Forms\Components\FileUpload::make('file')
            ->acceptedFileTypes(['text/csv']),
    ])
    ->action(fn (array $data) => static::import($data['file'])),

]);

Table Configuration

public static function table(Table $table): Table { return $table ->columns([...]) ->filters([...]) ->actions([...]) ->bulkActions([...])

    // Pagination
    ->paginated([10, 25, 50, 100])
    ->defaultPaginationPageOption(25)

    // Default sort
    ->defaultSort('created_at', 'desc')

    // Reordering
    ->reorderable('sort_order')
    ->defaultSort('sort_order')

    // Grouping
    ->groups([
        Tables\Grouping\Group::make('status')
            ->label('Status')
            ->collapsible(),
        Tables\Grouping\Group::make('author.name')
            ->label('Author'),
    ])

    // Striped rows
    ->striped()

    // Poll for updates
    ->poll('10s')

    // Empty state
    ->emptyStateHeading('No posts yet')
    ->emptyStateDescription('Create your first post to get started.')
    ->emptyStateIcon('heroicon-o-document-text')
    ->emptyStateActions([
        Tables\Actions\CreateAction::make()
            ->label('Create Post'),
    ])

    // Modals
    ->modals([
        'view' => true,
    ])

    // Persist filters
    ->filtersFormColumns(3)
    ->persistFiltersInSession();

}

Output

Generated tables include:

  • Complete column configuration

  • Search and sort settings

  • Filter definitions

  • Row and bulk actions

  • Relationship handling

  • Performance optimizations

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

filament-resource

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

resource

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

forms

No summary provided by upstream source.

Repository SourceNeeds Review