Getting started
Defining tracks & steps
Configuring your onboarding is very simple. First, I'll show you how to configure the widget. Next, I'll show you how to prevent users from accessing the dashboard without completing certain onboarding and how to make wizards.
It might be handy to know a little bit about how the package works. Two important concepts here are tracks and steps. Each track is a series of steps that a user has to complete. Your application typically has one or two tracks: one track for outside the admin panel and one track for the widget.
You can determine yourself using a closure when a step is viewed as "complete". If all steps in a track are complete, the whole track is deemed complete as well.
Creating a track
The place to create a track is in the panel() methods of each panel service provider that you want to use the plugin in.
Create a track using the $plugin->addTrack() method.
$plugin
->addTrack(fn () => Track::make([
/** Your steps */
]),
Please make sure that you put the
fn () =>before theTrack::make()part, so that the argument is a closure instead of a direct value. Otherwise, the logic in the plugin will be executed too early and it will throw an error.
Adding steps to a track
Next, you can add steps to a track by adding an array with steps. Create a single step by using the Step::make() method.
When using the admin widget, each step is represented by a nice card (see the images above).
The Step::make() method accepts two parameters:
- The name of the step. This name is displayed to the user.
- A unique identifier for the step. This identifier should be a string and is unique in your complete application.
Track::make([
Step::make(name: 'Connect Notion', identifier: 'widget::connect-notion')
/** Other configuration for the step... */
])
You can also provide a name using a closure:
Step::make(name: fn () => 'Hello ' . auth()->user()->first_name, identifier: 'greeting')
Adding a description
You can add a description for the step by adding the ->description() method. Provide either a string, an HtmlString or a closure.
Step::make(name: 'Connect Notion', identifier: 'widget::connect-notion')
->description('Sign in with Notion and grant access to your workspace.')
Adding an icon
You can add an icon (as string or as closure that returns string) to the step by using the ->icon() method:
Step::make(name: 'Connect Notion', identifier: 'widget::connect-notion')
->icon('heroicon-o-check-circle')
Setting a color
You can set the color of the icon using the ->color() method. The default is primary.
Step::make(name: 'Connect Notion', identifier: 'widget::connect-notion')
->icon('heroicon-o-check-circle')
->color('info')
Adding a url or action
Each Step can have a button at the bottom of the page. This button can either be a link/url or an advanced Filament action, including things like modals or forms.
You can use the ->url() method to add a link to the step. Combine this method with the performStepActionLabel() to define the label that should be on the button.
The link will be displayed to the user. You can use this to redirect to an OAuth provider or to a specific page in the dashboard:
Step::make(name: 'Connect Notion', identifier: 'widget::connect-notion')
->performStepActionLabel('Add workspace →')
->url(route('callbacks.notion.authorize'), shouldOpenInNewTab: true)
Alternatively, you can modify the performStepAction() to include any advanced code. This can include a modal or a form or any other PHP action that you want to run.
For example, this is an action that would open the "notifications" slide-over using Livewire:
Step::make(name: 'Notifications overview', identifier: 'open-notifications')
->performStepAction(function (Action $action) {
return $action
->label('Open notifications overview')
->action(function (OnboardTrackWidget $livewire) {
$livewire->dispatch('open-modal', id: 'database-notifications');
});
})
Determining if a step is complete
You can use the ->completeIf() method to specify a closure that will determine whether this step is complete. This closure should return a boolean:
Step::make(name: 'Connect Notion', identifier: 'widget::connect-notion')
->completeIf(fn () => auth()->user()->workspaces()->exists())
Allowing users to skip actions
You can also allow your users to skip a certain step. You can do this by providing a closure to the skippable() method. Below is an example of how this logically might work together:
Step::make(name: 'Notifications overview', identifier: 'open-notifications')
->completeIf(function () {
return auth()->user()->onboarding_notifications_completed;
})
->skippable(function () {
auth()->user()->onboarding_notifications_completed = true;
auth()->user()->save();
})
->performStepAction(function (Action $action) {
return $action
->label('Open notifications overview')
->action(function (OnboardTrackWidget $livewire) {
$livewire->dispatch('open-modal', id: 'database-notifications');
auth()->user()->onboarding_notifications_completed = true;
auth()->user()->save();
});
})
By default, a user will be prompted with a modal to confirm that they indeed want to skip the step. You can customize the modal details with the ->skipStepActionLabel(), ->skipStepActionColor(), ->skipStepActionModalHeading() and ->skipStepActionModalDescription() methods:
$step
->skipStepActionLabel('Skip notifications')
->skipStepActionColor('gray')
->skipStepActionModalHeading('Are you sure you want to skip this step?')
->skipStepActionModalDescription('Your notifications will always still arrive in your overview.')
Adding a column span
You can use the ->columnSpan() method to specify how many columns wide the card should be. You can use the Onboard::addTrack(/** Your steps */)->columns(/** Nr of columns */) to specify how many columns there should be in total.
You can even use an array to make the design responsive. It uses the same technique as the native Grid, so you can use the same techniques here.
Track::make([
Step::make(/** */)
->columnSpan(['default' => 1, 'md' => 1, 'lg' => 2, ])
// Other steps..
])
->columns(['default' => 1, 'md' => 3, 'lg' => 6, ])
Cards will automatically wrap to the next row.
The final result might look something like this:
use Filament\Facades\Filament;
use RalphJSmit\Filament\Onboard\FilamentOnboard;
public function panel(Panel $panel): Panel
{
return $panel
->default()
->id('admin')
->path('admin')
// Other panel configuration...
->plugin(
FilamentOnboard::make()
->addTrack(fn () => Track::make([
Step::make(name: 'Connect Notion', identifier: 'widget::connect-notion')
->description('Sign in with Notion and grant access to your workspace.')
->icon('heroicon-o-check-circle')
->performStepActionLabel('Add workspace →')
->url(route('callbacks.notion.authorize'))
->completeIf(fn () => auth()->user()->workspaces()->exists())
->columnSpan(1),
// Other steps
// Step::make(/** */)...
// Step::make(/** */)...
])->columns(3)
)
);
}
Allowing non-sequential steps
Normally, each Track is assumed to run sequentially: you need to complete Step 1, before being able to do Step 2. If this behaviour doesn't work for you or if you just want to provide a few steps using the widget that can be done in any order the user likes, you can use the ->sequential() function on the Track object to disable the sequential behaviour.
Track::make(fn () => [
// Steps can be completed in any order...
Step::make('First step', 'first-step')
->icon('heroicon-o-cube-transparent')
->url(FirstResource::getUrl()),
Step::make('Second step', 'second-step')
->icon('heroicon-o-cube')
->url(SecondStep::getUrl()),
])
->sequential(false)
Display the widget more compact
You can chain the ->compact() method to the track that you created in order to make the design more compact.
Using the widget
Now that we have defined our steps, we can register the widget class to use on the dashboard. You can also use the widget on resources and pages.
The widget class is RalphJSmit\Filament\Onboard\Widgets\OnboardTrackWidget.
You can register the widget via a panel service provider:
use RalphJSmit\Filament\Onboard\Widgets\OnboardTrackWidget;
$panel
->widgets([
OnboardTrackWidget::class,
])
Now your widget should be visible on the dashboard!