Spotlight

This component implements a global search feature triggered by a customizable shortcut. It does not index your site, so you need to implement by yourself a global search function.

Try it

Search for "a" to see what kind of content it returns. In this example, all links point to this page itself. You can change this default shortcut.

⌘ command + G

⊞ win + G

◆ meta + G

Usage

Place the spotlight tag somewhere on the main layout.

<body>
...
<x-spotlight />
</body>

Create a App\Support\Spotlight class with a search method that returns the result.

namespace App\Support;
 
class Spotlight
{
public function search(Request $request)
{
// Do your search logic here
// IMPORTANT: apply any security concern here
}
}

Make sure each item from your collection contains the following keys.

[
'name' => 'Mary', // Any string
'description' => 'Software Engineer', // Any string
'link' => '/users/1', // Any valid route
'avatar' => 'http://...' // Any image url
]

Instead of avatar you can use any pre-rendered blade icon.

[
// ...
'icon' => Blade::render("<x-icon name='o-bolt' />")
]

... You are done!

Manual activation

You can trigger the Spotlight component by dispatching a mary-search-open event. Probably you want to put this search button inside a navbar. In this case place an empty x-data as describe bellow.

{{-- Place an empty `x-data` on body--}}
<body ... x-data>
...
<nav>
{{-- Notice `@click.stop` --}}
<x-button label="Search" @click.stop="$dispatch('mary-search-open')" />
</nav>
 
<main>
{{ $slot }}
</main>
 
<x-spotlight />
</body>

Security

As maryUI exposes a public route to make Spotlight work, remember to apply any security concern directly on your search method.

Example

You can organize your search however you want. Don't be restricted exclusively to the approach shown in this example. But, here an example that mixes "users" and "app actions".

namespace App\Support;
 
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Blade;
 
class Spotlight
{
public function search(Request $request)
{
// Example of security concern
// Guests can not search
if(! auth()->user()) {
return [];
}
 
return collect()
->merge($this->actions($request->search))
->merge($this->users($request->search));
}
 
// Database search
public function users(string $search = '')
{
return User::query()
->where('name', 'like', "%$search%")
->take(5)
->get()
->map(function (User $user) {
return [
'avatar' => $user->profile_picture,
'name' => $user->name,
'description' => $user->email,
'link' => "/users/{$user->id}"
];
});
}
 
// Static search, but it could come from a database
public function actions(string $search = '')
{
$icon = Blade::render("<x-icon name='o-bolt' class='w-11 h-11 p-2 bg-yellow-50 rounded-full' />");
 
return collect([
[
'name' => 'Create user',
'description' => 'Create a new user',
'icon' => $icon,
'link' => '/users/create'
],
[
// More ...
]
])->filter(fn(array $item) => str($item['name'] . $item['description'])->contains($search, true));
}
}

Options

You can change the shortcut with any combination supported by Livewire.

<x-spotlight
shortcut="meta.slash"
search-text="Find docs, app actions or users"
no-results-text="Ops! Nothing here."
url="/custom/search/url/here" />

Changing the search class

If for some reason you want to change the search class, publish the config file.

php artisan vendor:publish --tag mary.config
// ...
'components' => [
'spotlight' => [
'class' => 'App\Support\Spotlight'
]
]

Slots

Add anything you want and dispatch a mary-search event with an extra query string.

You can do it in many ways. But, in this example we built it with Alpine.

<x-spotlight>
<div
x-data="{ query: { withUsers: true, withActions: true } }"
x-init="$watch('query', value => $dispatch('mary-search', new URLSearchParams(value).toString()))"
class="flex gap-8 p-3"
>
<x-checkbox label="Users" x-model="query.withUsers" />
<x-checkbox label="Actions" x-model="query.withActions" />
</div>
</x-spotlight>

Then, adjust your search method to handle those new request parameters.

class Spotlight
{
public function search(Request $request) {
// Do your logic here
}
}

maryUI
Sponsor