yacoubalhaidari/filament-tour

An interactive guided tour for Filament Admin Panel using Shepherd.js

Maintainers

Package info

github.com/YacoubAl-hardari/filament-tour

Homepage

pkg:composer/yacoubalhaidari/filament-tour

Statistics

Installs: 1 651

Dependents: 0

Suggesters: 0

Stars: 12

Open Issues: 0

v1.0.3 2026-06-04 18:23 UTC

This package is not auto-updated.

Last update: 2026-06-04 18:27:50 UTC


README

Gemini_Generated_Image_xwwnlrxwwnlrxwwn

Filament Tour

An interactive guided tour for the Filament admin panel powered by Shepherd.js.

This plugin adds a tour trigger button to the Filament user menu and lets you build a step‑by‑step walkthrough of your panel pages, with full control over colors, texts, and welcome/finish screens.

Features: Resources & custom pages · Livewire SPA navigation · Sidebar highlight + modal overlay · Custom welcome/finish · Progress resume · EN / AR / ID translations

Contents

🎥 Filament Tour – Video Demo

Filament Tour – Video Demo

Click the image to watch the full video on YouTube.

Requirements

  • PHP ^8.2
  • Filament ^3.0 or ^4.0

Installation

Require the package via Composer:

composer require yacoubalhaidari/filament-tour

Optionally publish the CSS/JS assets into your public directory (recommended in production so browsers load a stable copy):

php artisan filament-tour:assets
# or
php artisan filament:assets

This publishes:

  • public/css/yacoubalhaidari/filament-tour/filament-tour-styles.css
  • public/js/yacoubalhaidari/filament-tour/filament-tour-scripts.js

The service provider auto‑registers assets from the package (resources/dist/filament-tour.js, falling back to resources/js/shepherd-tour.js). After upgrading the package, run php artisan filament:assets and hard‑refresh the browser (Ctrl+Shift+R).

Registering the Plugin

In your Filament PanelProvider, register the plugin and optionally customize the tour button and appearance.

use Filament\Panel;
use YacoubAlhaidari\FilamentTour\FilamentTourPlugin;

class AdminPanelProvider extends PanelProvider
{
	public function panel(Panel $panel): Panel
	{
		return $panel
			->plugins([
				FilamentTourPlugin::make()
					// Show / hide the trigger button in the user menu
					->showTourButton(true)

					// Trigger button appearance
					->tourButtonIcon('heroicon-o-academic-cap')
					->tourButtonColor('info')
					->tourButtonTooltip(trans('filament-tour.tooltip'))

					// Color customization (all are optional)
					->headerColor('linear-gradient(135deg, #282835 0%, #282835 100%)')
					->primaryButtonColor('linear-gradient(135deg, #282835 0%, #282835 100%)')
					->secondaryButtonColor('linear-gradient(135deg, #282835 0%, #282835 100%)')
					->textColor('#1f2937')
					->backgroundColor('linear-gradient(135deg, #282835 0%, #282835 100%)')
					->contentBackgroundColor('#282835')
					->footerBackgroundColor('linear-gradient(180deg, #282835 0%, #282835 100%)')
					->primaryButtonHoverColor('linear-gradient(135deg, #ea580c 0%, #dc2626 100%)')
					->secondaryButtonHoverColor('linear-gradient(135deg, #282835 0%, #282835 100%)')
					->primaryButtonTextColor('#ffffff')
					->secondaryButtonTextColor('#ffffff')
					->footerBorderColor('rgba(0, 0, 0, 0.1)')

					// Optional custom welcome & finish steps
					->welcomeStep([
						'id' => 'welcome',
						'title' => 'مرحباً مخصص!',
						'text' => '<strong>رسالة ترحيب مخصصة</strong>',
						'buttons' => [
							['text' => 'تخطي', 'action' => 'cancel', 'secondary' => true],
							['text' => 'ابدأ', 'action' => 'next', 'secondary' => false],
						],
					])
					->finishStep([
						'id' => 'finish',
						'title' => 'تهانينا مخصص!',
						'text' => '<strong>رسالة إنهاء مخصصة</strong>',
						'buttons' => [
							['text' => 'السابق', 'action' => 'back', 'secondary' => true],
							['text' => 'إنهاء', 'action' => 'complete', 'secondary' => false],
						],
					]),
			]);
	}
}

Plugin Methods

All configuration methods are chainable on FilamentTourPlugin::make():

  • showTourButton(bool $condition = true) – Show or hide the tour trigger icon in the user menu.
  • tourButtonIcon(string $icon) – Heroicon or custom icon class for the trigger button.
  • tourButtonColor(string $color) – Filament color name (e.g. info, primary, success).
  • tourButtonTooltip(string $tooltip) – Tooltip text shown when hovering the trigger button.

Color customization (all optional – values are used directly as CSS values and wired into CSS variables):

  • headerColor(string $color) – Header background (e.g. gradient or hex color).
  • primaryButtonColor(string $color) – Primary button background.
  • secondaryButtonColor(string $color) – Secondary button background.
  • textColor(string $color) – Main text color inside the tour.
  • backgroundColor(string $color) – Overall tour background.
  • contentBackgroundColor(string $color) – Content area background.
  • footerBackgroundColor(string $color) – Footer background (where buttons sit).
  • primaryButtonHoverColor(string $color) – Primary button hover background.
  • secondaryButtonHoverColor(string $color) – Secondary button hover background.
  • primaryButtonTextColor(string $color) – Text color inside the primary button.
  • secondaryButtonTextColor(string $color) – Text color inside the secondary button.
  • footerBorderColor(string $color) – Border color above the footer.

Custom welcome / finish steps:

  • welcomeStep(array $step) – Override the default first step.
  • finishStep(array $step) – Override the default last step.

Each step array supports at least:

[
	'id' => 'welcome',               // Unique step ID
	'title' => 'عنوان الخطوة',       // Step title
	'text' => '<strong>HTML</strong>', // Step body (HTML allowed)
	'buttons' => [
		['text' => 'تخطي', 'action' => 'cancel',   'secondary' => true],
		['text' => 'التالي', 'action' => 'next',   'secondary' => false],
		['text' => 'السابق', 'action' => 'back',   'secondary' => true],
		['text' => 'إنهاء', 'action' => 'complete','secondary' => false],
	],
]

Supported button actions: back, next, cancel, complete.

Defining Dynamic Tour Steps

Dynamic steps are collected automatically by TourStepCollector from:

  • Filament Resources that use HasTourSteps
  • Filament Pages (custom pages) that use HasTourSteps

Steps are sorted by getTourStepSort() (lower = earlier). The tour order is:

welcomeStep → dynamic steps → finishStep

On Resources

Add the trait to any resource you want to appear in the tour:

use Filament\Resources\Resource;
use YacoubAlhaidari\FilamentTour\Concerns\HasTourSteps;

class MerchantResource extends Resource
{
	use HasTourSteps;

	public static function getTourStepId(): ?string
	{
		return 'merchants-list';
	}

	public static function getTourStepTitle(): ?string
	{
		return 'إدارة التجار';
	}

	public static function getTourStepDescription(): ?string
	{
		return 'وصف موجز لما يمكن للمستخدم القيام به هنا.';
	}

	public static function getTourStepFeatures(): array
	{
		return [
			'إضافة تاجر جديد',
			'تعديل بيانات التاجر',
			'عرض حالة المحافظ والطلبات',
		];
	}

	public static function getTourStepPosition(): string
	{
		// Shepherd position: top|bottom|left|right|center ...
		return 'right';
	}

	public static function getTourStepSort(): int
	{
		// Lower numbers appear earlier in the tour
		return 10;
	}
}

What the Trait Provides

HasTourSteps defines the following static methods (with sensible defaults):

  • getTourSteps(): array – Low-level hook if you want to return fully custom step definitions (defaults to []).
  • getTourStepId(): ?string – Unique ID for the step (also used as data-tour value).
  • getTourStepTitle(): ?string – Step title (defaults to getModelLabel() on resources, or getNavigationLabel() on pages).
  • getTourStepDescription(): ?string – Short description paragraph.
  • getTourStepFeatures(): array – Bullet list of features; rendered as a list in the tooltip.
  • getTourStepPosition(): string – Tooltip position relative to the target (default right).
  • getTourStepSort(): int – Sort order (lower = earlier in the tour; default 100).
  • getTourSelector(): ?string – Selector used to attach the step (defaults to getTourStepId()).
  • hasTourStep(): bool – Whether the resource should participate in the tour.

The package collects these steps via TourStepCollector and passes them to the frontend as window.dynamicTourSteps.

For resources, the collector resolves the step URL with Resource::getUrl('index') so the tour can navigate to the list page when needed.

On Custom Pages

Use the same trait on a Filament Page class (must be registered on the panel):

use Filament\Pages\Page;
use YacoubAlhaidari\FilamentTour\Concerns\HasTourSteps;

class SignBuilder extends Page
{
    use HasTourSteps;

    protected static ?string $navigationLabel = 'Sign Builder';

    public static function getTourStepId(): ?string
    {
        return 'sign-builder';
    }

    public static function getTourStepTitle(): ?string
    {
        return 'Sign Builder';
    }

    public static function getTourStepDescription(): ?string
    {
        return 'Place signature fields on your PDF documents.';
    }

    public static function getTourStepFeatures(): array
    {
        return [
            'Add signature fields',
            'Assign signers',
            'Navigate document pages',
        ];
    }

    public static function getTourStepSort(): int
    {
        return 40;
    }
}

For pages, the collector uses Page::getUrl() (no index route). getTourStepTitle() falls back to getNavigationLabel() when getModelLabel() is not available.

How Navigation Matching Works

The frontend tags sidebar items with data-tour="{stepId}" so Shepherd can highlight the correct menu entry.

Matching strategy (in order)

  1. URL path (recommended) – Each dynamic step includes a url. Links in the sidebar (.fi-sidebar-item-btn) whose href pathname matches that URL receive data-tour.
  2. Navigation label (fallback)TourStepCollector::getNavigationMap() builds { stepId => navigationLabel } from getNavigationLabel() on each resource/page. Sidebar text is matched against the label.

While the tour runs

  • Shepherd modal overlay – Darkens the panel and cuts a hole around the target element.
  • .shepherd-target – Orange outline on the attached element (see resources/css/shepherd-tour.css).
  • .shepherd-tour-active-nav – Extra highlight on the active sidebar item during the step.

Livewire SPA navigation

When a step belongs to another resource/page, the tour:

  1. Calls Livewire.navigate() to the step URL (if available).
  2. Waits for livewire:navigated.
  3. Re-applies data-tour attributes and waits for the target element in the DOM.
  4. Re-binds the modal overlay on the sidebar item.

This avoids stale DOM references after Filament replaces the page content.

Welcome & finish steps

Steps without attachTo (default welcome/finish, or your custom welcomeStep() / finishStep()) are centered and use a lighter experience: the full-screen dark overlay is hidden so only the tooltip card is shown.

Localization (en / ar / id)

The package ships with simple translation files that you can override in your app:

  • resources/lang/en/filament-tour.php
  • resources/lang/ar/filament-tour.php
  • resources/lang/id/filament-tour.php

Each file contains default labels for the welcome/finish steps and button texts. You can override them in your own application like any other Laravel lang file and then map them into your custom welcomeStep() / finishStep() calls, for example:

FilamentTourPlugin::make()
	->welcomeStep([
		'id' => trans('filament-tour.welcome.id'),
		'title' => trans('filament-tour.welcome.title'),
		'text' => trans('filament-tour.welcome.text'),
		'buttons' => [
			['text' => trans('filament-tour.welcome.buttons.skip'),  'action' => 'cancel',   'secondary' => true],
			['text' => trans('filament-tour.welcome.buttons.start'), 'action' => 'next',     'secondary' => false],
		],
	])
	->finishStep([
		'id' => trans('filament-tour.finish.id'),
		'title' => trans('filament-tour.finish.title'),
		'text' => trans('filament-tour.finish.text'),
		'buttons' => [
			['text' => trans('filament-tour.finish.buttons.back'),   'action' => 'back',     'secondary' => true],
			['text' => trans('filament-tour.finish.buttons.finish'), 'action' => 'complete', 'secondary' => false],
		],
	]);

Running the Tour

  • Click the tour icon in the Filament user menu (default heroicon-o-academic-cap).
  • The tour starts at the welcome step (default or your custom welcomeStep).
  • Dynamic steps run in order of getTourStepSort().
  • The final step is the finish screen (default or your custom finishStep).

Progress persistence

The tour stores state in the browser:

Key Purpose
shepherd-tour-in-progress "true" while the tour is active
shepherd-tour-current-step Current step id (e.g. users, documents)
shepherd-tour-completed Set when the user finishes the tour
shepherd-tour-completed-at ISO timestamp of completion

If the user refreshes or Livewire navigates during a tour, the script can resume from shepherd-tour-current-step.

After complete or cancel

cleanupTourState() runs automatically:

  • Removes tour CSS classes (.shepherd-tour-active-nav, .shepherd-target, modal overlay).
  • Clears in-progress localStorage keys.
  • Syncs sidebar active state to the current URL (fi-active on the matching menu item only), so the dashboard is not incorrectly highlighted after visiting other pages during the tour.

Building Frontend Assets (package contributors)

If you modify resources/js/shepherd-tour.js, rebuild the bundle:

cd packages/filament-tour   # or the package root in vendor
npm install
node bin/build.js

Output: resources/dist/filament-tour.js

Then publish to your app:

php artisan filament:assets

Troubleshooting

Highlight works on the first step only

  1. Run php artisan filament:assets and hard‑refresh the browser.
  2. Ensure getTourStepId() is unique across resources and pages.
  3. Ensure the resource has an index URL (or the page is navigable).
  4. Check the browser console for Tour target not found for step "...".
  5. Confirm sidebar labels match getNavigationLabel() or that the menu link href matches the step URL.

Wrong sidebar item active after the tour

This is handled by syncSidebarActiveState() on complete/cancel. If you use a custom sidebar, ensure menu links use standard Filament classes (.fi-sidebar-item, .fi-sidebar-item-btn) and correct href paths.

Custom welcome/finish still show a black screen

Use welcomeStep() / finishStep() without attachTo. Centered steps hide the modal overlay automatically.

Translations not applied to buttons in dynamic steps

Dynamic step buttons use __('filament-tour::filament-tour.buttons.*') from the collector. Publish or override lang files in your app under lang/vendor/filament-tour/ if needed.

License

Released under the MIT License.