On my Mac, I always enjoy how quickly I can open applications, run commands and navigate through the OS via the command palette known as Spotlight. So I thought how great it would be to have this on the web as well. So I went ahead and got going to build Laravel Spotlight for one of my projects, Unlock. A few days later, I published the repository, and the response has been amazing.
This tutorial will show you how you can use Laravel Spotlight to enhance your application and improve the user experience. Fair warning, once you implement this, chances are you will want to use this for all your applications ;)
Installation
Installing Laravel Spotlight only takes a few minutes. Let's start by downloading the package from Composer:
composer require wire-elements/spotlight
Next, you will need to add the @livewire
directive to your main template file like views/resources/layouts/app.blade.php
:
@livewire('livewire-ui-spotlight')
@livewireScripts
</body>
</html>
Laravel Spotlight requires Alpine, so you can either add this to your package.json or include the minified version from the UNPKG CDN:
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
Finally, let's publish the configuration file, which I will reference in future steps.
php artisan vendor:publish --tag=livewire-ui-spotlight-config
Opening Spotlight
You should now see the command prompt popup once you use one of the following shortcuts:
- CTRL + K
- CMD + K
- CTRL + /
- CMD + /
You can adjust these shortcuts in the livewire-ui-spotlight.php
config file:
<?php
return [
/*
|--------------------------------------------------------
| Shortcuts
|--------------------------------------------------------
|
| Define which shortcuts will activate Spotlight CTRL / CMD + key
| The default is CTRL/CMD + K or CTRL/CMD + /
|
*/
'shortcuts' => [
'k',
'slash',
],
Additionally, you can also toggle Spotlight by using browser events from either other Livewire components or by using Alpine's $dispatch
helper:
<?php
class MyComponent extends Component {
public function openSpotlight()
{
$this->dispatchBrowserEvent('toggle-spotlight');
}
}
<button @click="$dispatch('toggle-spotlight')">Toggle Spotlight</button>
Creating your first Spotlight command
Now that we have the basics covered, we can continue with creating our very first Spotlight command. The possibilities are endless, but one of the easiest and most productive commands is a command that helps you navigate to different parts of your application, e.g., viewing the details of a specific user.
So let's start by using the make:spotlight
command and create our command:
php artisan make:spotlight ViewUser
The artisan:make command will create a new class, open app\Spotlight\ViewUser.php
and define the name and description of our command:
<?php
namespace App\Spotlight;
use LivewireUI\Spotlight\SpotlightCommand;
class ViewUser extends SpotlightCommand
{
protected string $name = 'View User';
protected string $description = 'View a given user';
//
}
The command will not show up until we've registered it, so let's do this right now. Spotlight supports two different approaches to register commands; you can either add your command to the livewire-ui-spotlight.php
file:
<?php
return [
//
'commands' => [
\LivewireUI\Spotlight\Commands\Logout::class
],
];
Alternatively, you can register commands from your service provider:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
Spotlight::registerCommand(ViewUser::class);
}
}
One benefit of using the ServiceProvider is the ability to register commands conditionally:
Spotlight::registerCommandIf(true, ViewUser::class);
Spotlight::registerCommandUnless(false, ViewUser::class);
In some cases, you might want to show or hide commands based on the user; this can be achieved with the shouldBeShown
method, which we will discuss shortly.
If you open Spotlight and start typing, you will see the ViewUser
command in the list of commands:
Defining Spotlight dependencies
Commands can include dependencies like the one we are building right now. When referring to dependencies, I mean additional arguments you would like to ask from the user. In this case, we want to search for available users to view.
To define dependencies, we need to provide Spotlight with a SpotlightCommandDependencies
collection. Let's take a look:
class ViewUser extends SpotlightCommand
{
protected string $name = 'View User';
protected string $description = 'View a given user';
public function dependencies(): ?SpotlightCommandDependencies
{
return SpotlightCommandDependencies::collection()
->add(
SpotlightCommandDependency::make('user')
->setPlaceholder('Which user do you want to view?')
);
}
We register our dependencies by creating a public function called dependencies
which will return an instance of SpotlightCommandDependencies
. You can register an unlimited number of placeholders, but we will stick with just one in this example. Our dependency is called user, which we will reference later to search and get the associated value. We also provided a placeholder which the command prompt will show when asking for the user dependency.
Now that our command is aware of the dependency, we need to tell it how to search and resolve users to view. We can do this by creating a new method called searchUser
, the second part of this method must match the name of your dependency. The IoC container will resolve any method parameters. For our ViewUser
command, we want to get the input query from our user. To do this, you just add $query
as the searchUser
method argument:
public function searchUser($query)
{
return User::where('name', 'like', "%$query%")
->get()
->map(function(User $user) {
return new SpotlightSearchResult(
$user->id,
$user->name,
sprintf('View user %s', $user->name)
);
});
}
You can use any way you like to search; in this example, we use Eloquent to search our MySQL database, but you could also use Laravel Scout, for example. Search results must be mapped into a SpotlightSearchResult
instance. This class requires three arguments, a unique identifier for the search result, a value to display, and optionally a description.
If you have multiple dependencies, you will have access to every previous dependency to allow scoped searching. For example:
return SpotlightCommandDependencies::collection()
->add(
SpotlightCommandDependency::make('user')
->setPlaceholder('Which user do you want to view?')
)
->add(
SpotlightCommandDependency::make('foobar')
->setPlaceholder('Search for second dependency')
);
Now, the foobar
dependency will have access to the user
dependency:
public function searchFoobar($query, User $user)
{
// Given Foobar is the second dependency it will have access to any resolved depedencies defined earlier. In this case we can access the User which was chosen.
}
Executing commands
Once the user provides all our dependencies, we can continue and execute our command. We can do this by creating a new method called execute
. This method resolves any dependencies from the Laravel IoC container, including our command dependencies:
public function execute(User $user)
{
dd($user); // Returns the resolved User modal.
}
Now that we have our User modal, we can redirect the user to the user profile:
public function execute(User $user)
{
return redirect()->route('users.show', $user);
}
In some cases, you might want to interact with the Spotlight Livewire component itself. For example, you might want to integrate your command with the Wire Elements modal package:
Adding support for multiple dependency types to Spotlight. Besides search dependencies, you can now also define input dependencies. This allows you to create new models on the fly, pre-fill form inputs, and anything else you might think of π₯ Laravel β€οΈ Livewire pic.twitter.com/w5SVt591CV
— Philo Hermans (@Philo01) April 23, 2021
In order to do this, we need to inject the Spotlight Livewire component instance and emit the openModal
event to which the modal is listening:
use LivewireUI\Spotlight\Spotlight;
public function execute(Spotlight $spotlight, User $user)
{
$spotlight->emit('openModal', 'view-user', ['user' => $user->id]);
}
And that's it, just hit your Spotlight shortcut, choose the "View user" command, enter the name of the user, and hit enter to see the modal appear.
I've already seen people implement Spotlight days after the initial launch π
Super excited about this new spotlight feature π€© pic.twitter.com/6HR8hKIzNy
— ππ²πΉπΆπ π¦π°π΅πΌπΉπ π¦ (@scholz_felix) April 23, 2021
I'm looking forward to seeing what you are building with Laravel Spotlight π Be sure to share your result with me on Twitter.
I'm thinking about releasing a premium video course in the near future (if enough people are interested) where I will show you how to build a real-world application from start to finish using Laravel, Livewire, and Tailwind CSS. I will be covering everything, from registering a domain, setting up a server, writing tests, you name it. Subscribe if you are interested and want to be notified, and you might also get access for free as I will be doing a giveaway when the course launches.