leek/filament-header-filters
Add inline filters to Filament table column headers. Attach any BaseFilter (selects, date pickers, min/max ranges, custom schemas) as a richer alternative to individual searchable fields. Works with Filament v4/v5, PHP 8.2+.
Inline header filters for Filament tables. Attach any BaseFilter to a column header — select dropdowns, date pickers, min/max ranges, custom multi-field schemas — as a richer alternative to searchable(isIndividual: true).

composer require leek/filament-header-filters
Add the HasHeaderFilters trait to any Livewire component that uses InteractsWithTable (resource list pages, custom Livewire table components):
use Filament\Resources\Pages\ListRecords;
use Leek\FilamentHeaderFilters\Concerns\HasHeaderFilters;
class ListOrders extends ListRecords
{
use HasHeaderFilters;
}
Add the package stylesheet to the panel theme configured with ->viteTheme(...). Place it after Filament's theme import so it can adjust the table and header filter styles:
@import '../../../../vendor/filament/filament/resources/css/theme.css';
@import '../../../../vendor/leek/filament-header-filters/resources/css/filament-header-filters.css';
Then rebuild your app assets:
npm run build
If you are using Vite locally, restart or keep running:
npm run dev
Call ->headerFilter() on any column and pass a filter instance.
Use SelectFilter for exact-match column filtering. The default placeholder is "All".
use App\Enums\OrderStatus;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
TextColumn::make('status')
->badge()
->headerFilter(
SelectFilter::make('status')
->options(OrderStatus::class)
->native(false)
)
Use a custom Filter with two TextInput fields and ->columns(2) for a side-by-side numeric range:
use Filament\Forms\Components\TextInput;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;
TextColumn::make('total_price')
->headerFilter(
Filter::make('total_price_range')
->columns(2)
->schema([
TextInput::make('min')->numeric()->placeholder('Min'),
TextInput::make('max')->numeric()->placeholder('Max'),
])
->query(fn (Builder $query, array $data): Builder => $query
->when($data['min'] ?? null, fn (Builder $q, $v): Builder => $q->where('total_price', '>=', $v))
->when($data['max'] ?? null, fn (Builder $q, $v): Builder => $q->where('total_price', '<=', $v))
)
)
Use DatePicker fields for a two-date range:
use Filament\Forms\Components\DatePicker;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;
TextColumn::make('created_at')
->label('Order date')
->date()
->headerFilter(
Filter::make('order_date_range')
->columns(2)
->schema([
DatePicker::make('from')->placeholder('From')->native(false),
DatePicker::make('until')->placeholder('Until')->native(false),
])
->query(fn (Builder $query, array $data): Builder => $query
->when($data['from'] ?? null, fn (Builder $q, $v): Builder => $q->whereDate('created_at', '>=', $v))
->when($data['until'] ?? null, fn (Builder $q, $v): Builder => $q->whereDate('created_at', '<=', $v))
)
)
$tableFilters). Filter indicators, reset, and session persistence all work.deferFilters().If a table has only header filters and no panel filters, hide the filters dropdown so the button doesn't render empty:
use Filament\Tables\Enums\FiltersLayout;
public function table(Table $table): Table
{
return $table
->filtersLayout(FiltersLayout::Hidden)
->columns([
TextColumn::make('status')->headerFilter(/* ... */),
// ...
]);
}
Filacheck's missing-table-filters rule doesn't recognize ->headerFilter() and will flag tables that only use header filters. Publish the config and disable the rule:
php artisan vendor:publish --tag=filacheck-config
// config/filacheck.php
'missing-table-filters' => [
'enabled' => false,
],
The package ships:
Column::macro('headerFilter', ...), getHeaderFilter(), hasHeaderFilter()BaseFilter::macro('columnName', ...), getColumnName(), isHeaderFilter()Table::macro('getHeaderFilters', ...), hasHeaderFilters()HasHeaderFilters Livewire trait that wires filters into the table, seeds header filter state, and exposes getTableHeaderFiltersForm()filament-tables::index) that renders the header filter row under the column search rowThe view override is a patched copy of Filament's table view. If you upgrade Filament and something breaks, please open an issue.
composer test
MIT. See LICENSE.md.
How can I help you explore Laravel packages today?