jibaymcs/filament-tour
Add DriverJS-powered guided tours to your Filament panels. Register tours on pages with a simple trait, define steps with titles/descriptions, and optionally show tours only once via localStorage. Supports Filament v2–v5 with easy plugin setup.
Installation:
composer require jibaymcs/filament-tour:"^5.0"
Publish config (optional):
php artisan vendor:publish --tag="filament-tour-config"
Register Plugin:
Add to your panel() method in AppServiceProvider or PanelProvider:
->plugins([FilamentTourPlugin::make()])
First Tour:
HasTour trait in your dashboard/page class:
use JibayMcs\FilamentTour\Tour\HasTour;
class Dashboard extends FilamentDashboard {
use HasTour;
public function tours(): array {
return [
Tour::make('dashboard')
->steps(
Step::make()
->title("Welcome!")
->description("This is your first tour step.")
)
];
}
}
Create a simple dashboard tour to guide new users through key features:
public function tours(): array {
return [
Tour::make('dashboard')
->steps(
Step::make('.fi-header-heading')
->title("Dashboard Overview")
->description("This is your main dashboard area.")
->icon('heroicon-o-home')
->iconColor('primary'),
Step::make('.fi-avatar')
->title("User Profile")
->description("Click here to manage your account.")
)
];
}
Element-Based Tours:
Step::make('.filament-table')
->title("Data Tables")
->description("Interact with your data here.")
Modal Steps (no element selector):
Step::make()
->title("Important Notice")
->description(view('tours.notice'))
->uncloseable(true)
Dynamic Tours (using closures):
Step::make('.filament-widget')
->title(fn() => "Widget: " . auth()->user()->name)
->description(fn() => "Your personalized widget area.")
Use Livewire events to trigger tours based on logic:
#[On('filament-tour::loaded-elements')]
public function checkTourConditions(bool $onlyVisibleOnce, array $tours): void {
if (auth()->user()->hasRole('admin') && empty(auth()->user()->completedTours)) {
$this->dispatch('filament-tour::open-tour', 'admin-onboarding');
}
}
For complex tours, define in JSON and load dynamically:
Tour::make(json: Storage::disk('local')->get('complex-tour.json'))
->route('/admin/reports')
Combine tours with persistent highlights:
public function highlights(): array {
return [
Highlight::make('.fi-actions')
->element('.fi-actions')
->title("Actions Menu")
->description("Quick actions for this resource.")
->icon('heroicon-o-chevron-down')
->position('bottom-right')
];
}
Event-Driven Triggers:
filament-tour::open-tour/open-highlight events for button-triggered tours:
<button wire:click="$dispatch('filament-tour::open-tour', 'wizard-tour')">
Start Wizard Tour
</button>
Tour States Management:
onlyVisibleOnce for reusable tours:
FilamentTourPlugin::make()->onlyVisibleOnce(false)
Dark/Light Mode:
Tour::make('dashboard')
->colors('gray-100', 'gray-800')
Development Workflow:
FilamentTourPlugin::make()->enableCssSelector()
Ctrl+Space to open the selector tool and copy elements.Element Selector Issues:
.filament-table vs .filament-table tr).Ctrl+Space) to debug.Step::make('#resource-table tbody tr')
Route Mismatches:
Tour::make()->route('/admin/resources')
ignoreRoutes(true) for global tours (use sparingly).Event Conflicts:
clickOnNext or dispatchOnNext events don’t fire.disableEvents(false) is set.Caching:
onlyVisibleOnce(false).localStorage.removeItem('filament-tour-seen');
Inspect Tour Data:
#[On('filament-tour::loaded-elements')]
public function debugTours(bool $onlyVisibleOnce, array $tours) {
\Log::info('Available Tours:', $tours);
}
DriverJS Console:
View Source:
<div class="driverjs-tour" style="display: none;">
Custom Step Types:
Step to add custom behaviors:
class CustomStep extends Step {
public function customAction(string $action) {
// Logic for custom actions
}
}
Theme Overrides:
filament-tour views to customize styling:
php artisan vendor:publish --tag="filament-tour-views"
Storage Backend:
onlyVisibleOnce logic to use a database:
FilamentTourPlugin::make()->onlyVisibleOnce(
fn() => !TourSeen::where('user_id', auth()->id())->exists()
);
Advanced Events:
document.addEventListener('driverjs:step:show', (e) => {
console.log('Step shown:', e.detail);
});
only_visible_once:
true; set to false for reusable tours:
FilamentTourPlugin::make()->onlyVisibleOnce(false);
Tour ID Prefixing:
tour_dashboard). Account for this when dispatching events:
$this->dispatch('filament-tour::open-tour', 'tour_dashboard');
JSON Validation:
id, steps). Missing fields may cause silent failures.Livewire Compatibility:
HasTour trait is used on the root component (not nested components).How can I help you explore Laravel packages today?