felipearnold/filament-stepped-tabs
| Install | |
|---|---|
composer require felipearnold/filament-stepped-tabs |
|
| Latest Version: | v1.1.1 |
| PHP: | ^8.1 |
| License: | MIT |
| Last Updated: | Oct 3, 2026 |
| Links: | GitHub · Packagist |
Filament Stepped Tabs
Chevron-style stepped tabs navigation with counters, for Filament (and any Livewire) pages.
Why
Filament's built-in Tabs component renders a pill-style tab bar. This package renders the same
"steps"/breadcrumb look — chevron-shaped segments, a bold label, a small counter underneath, active
step highlighted — and plugs into any Livewire component, not just Filament resource pages.
The core (StepTab builder + InteractsWithSteppedTabs trait) has no dependency on Filament
internals — it only requires Livewire. The Blade view uses <x-filament::icon> (from
filament/support, present in every Filament major) for the optional per-step icon.
Installation
composer require felipearnold/filament-stepped-tabs
Usage
Filament v4/v5 ListRecords with getTabs() (recommended)
Keep your regular Filament tabs and add HasSteppedTabs. The page's getTabs() is rendered as stepped
tabs: label and icon come from each Tab, and the counter is the number of records of that tab with the
current table filters and search applied.
use FelipeArnold\FilamentSteppedTabs\Concerns\HasSteppedTabs;
use Filament\Schemas\Components\Tabs\Tab;
class ListInvoices extends ListRecords
{
use HasSteppedTabs;
public function getTabs(): array
{
return [
'draft' => Tab::make('Drafts')
->icon('heroicon-o-pencil-square')
->modifyQueryUsing(fn (Builder $query) => $query->where('status', 'draft')),
'all' => Tab::make('All')->icon('heroicon-o-queue-list'),
];
}
}
The active step is bound to Filament's own $activeTab property, so ?tab= in the URL, the default tab
and modifyQueryUsing() keep working unchanged. Each step runs one count() query.
Custom steps on any Livewire component
1. Add the trait to your Livewire component
use FelipeArnold\FilamentSteppedTabs\Concerns\InteractsWithSteppedTabs;
class ListEnvelopes extends ListRecords
{
use InteractsWithSteppedTabs;
public function getDefaultActiveStep(): ?string
{
return 'sent';
}
}
2. Build your steps with StepTab
use FelipeArnold\FilamentSteppedTabs\StepTab;
public function getSteps(): array
{
$counts = Envelope::query()->where('tenant_id', $tenant->id)
->selectRaw('status, count(*) as total')->groupBy('status')->pluck('total', 'status');
return [
StepTab::make('draft')->label('Rascunhos')->icon('heroicon-o-pencil-square')->count($counts->get('draft', 0))->toArray(),
StepTab::make('cancelled')->label('Cancelados')->icon('heroicon-o-x-circle')->count($counts->get('cancelled', 0))->toArray(),
StepTab::make('expired')->label('Expirados')->icon('heroicon-o-calendar')->count($counts->get('expired', 0))->toArray(),
StepTab::make('sent')->label('Em andamento')->icon('heroicon-o-paper-airplane')->count($counts->get('sent', 0))->toArray(),
StepTab::make('signed')->label('Assinados')->icon('heroicon-o-check-circle')->count($counts->get('signed', 0))->toArray(),
StepTab::make('all')->label('Todos')->icon('heroicon-o-inbox')->count($counts->sum())->toArray(),
];
}
3. Render it and filter your query by $this->activeStep
Filament v4/v5 (inside a ListRecords page, replacing getTabsContentComponent()):
use Filament\Schemas\Components\Component;
use Filament\Schemas\Components\View;
public function getTabsContentComponent(): Component
{
return View::make('filament-stepped-tabs::components.nav')
->viewData(['steps' => $this->getSteps(), 'activeStep' => $this->activeStep]);
}
protected function getTableQuery(): Builder
{
$query = parent::getTableQuery();
return $this->activeStep && $this->activeStep !== 'all'
? $query->where('status', $this->activeStep)
: $query;
}
Filament v3 (no Schemas package — render inside the page's Blade view or via a renderHook):
{{-- resources/views/filament/resources/envelopes/pages/list-envelopes.blade.php --}}
<x-filament-panels::page>
@include('filament-stepped-tabs::components.nav', ['steps' => $this->getSteps(), 'activeStep' => $this->activeStep])
{{ $this->table }}
</x-filament-panels::page>
Plain Blade / any Livewire component:
<x-filament-stepped-tabs::nav :steps="$this->getSteps()" :active-step="$activeStep" />
The view also accepts property (default activeStep): the Livewire property set when a step is clicked.
Step options
| Method | Description |
|---|---|
StepTab::make(string $key) |
Unique key ([a-z0-9_-]+), used for activeStep matching |
->label(string $label) |
Display label (defaults to the key) |
->count(int $count) |
Counter shown under the label |
->icon(string|BackedEnum|Htmlable|null $icon) |
Optional icon (name or Heroicon enum), rendered via x-filament::icon |
->color(?string $color) |
Reserved for future theming |
Translations
The step counter ("1 item", "3 items") follows the app locale. Bundled: en, pt_BR and pt_PT.
Publish to customize or add a locale:
php artisan vendor:publish --tag="filament-stepped-tabs-translations"
Testing
composer test
License
MIT.
Related Packages
Automatically refresh the Filament sidebar navigation when certain events occur,...
A beautiful file manager plugin for Filament. Browse, upload, rename, move and d...
A comprehensive Laravel Filament 3 💡 starter kit with pre-installed plugins, ad...
Version History
| Version | Released | PHP | Laravel | License |
|---|---|---|---|---|
| v1.1.1 | ^8.1 | MIT | ||
| v1.1.0 | ^8.1 | MIT | ||
| v1.0.3 | ^8.1 | MIT | ||
| v1.0.2 | ^8.1 | MIT | ||
| v1.0.1 | ^8.1 | ^10.0| | MIT | |
| v1.0.0 | ^8.1 | ^10.0| | MIT |