# Wire Elements Spotlight Wire Elements Spotlight is a Livewire component that provides Spotlight/Alfred-like functionality to Laravel applications. It enables users to quickly search and execute commands using a keyboard-activated search interface, similar to macOS Spotlight or the Alfred app. The package integrates seamlessly with Laravel's service container for dependency injection and supports Livewire v3. The core functionality centers around creating custom commands that users can search and execute through a floating search modal. Commands can have dependencies that require additional user input (like selecting a team before creating a user), support search synonyms for better discoverability, and can be conditionally shown based on user permissions or application state. The package uses Fuse.js for fuzzy search matching on the frontend. ## Installation Install the package via Composer and add the Livewire directive to your layout. ```bash composer require wire-elements/spotlight ``` ```html
@livewireStyles {{ $slot }} @livewire('livewire-ui-spotlight') @livewireScripts ``` ## Configuration Publish and customize the configuration file to set keyboard shortcuts, register commands, and control CSS/JS inclusion. ```bash php artisan vendor:publish --tag=livewire-ui-spotlight-config ``` ```php // config/livewire-ui-spotlight.php [ 'k', // CTRL/CMD + K 'slash', // CTRL/CMD + / ], // Register commands globally 'commands' => [ \App\Spotlight\SearchUsers::class, \App\Spotlight\NavigateToSettings::class, \LivewireUI\Spotlight\Commands\Logout::class, ], // Enable if not using TailwindCSS 'include_css' => false, // Set to false if bundling JS yourself 'include_js' => true, // Show all commands before user types anything 'show_results_without_input' => false, ]; ``` ## Creating a Basic Command Create a simple command that executes an action when selected. Use the artisan command to generate the boilerplate. ```bash php artisan make:spotlight NavigateToSettings ``` ```php // app/Spotlight/NavigateToSettings.php redirect('/settings'); } } ``` ## Creating Commands with Dependencies Create commands that require user input through searchable dependencies. Dependencies are resolved in order and can access previously selected values. ```php // app/Spotlight/CreateUserForTeam.php add( SpotlightCommandDependency::make('team') ->setPlaceholder('Select a team...') ) ->add( SpotlightCommandDependency::make('role') ->setPlaceholder('Select a role for this user...') ) ->add( // INPUT type for free-text entry instead of searchable list SpotlightCommandDependency::make('email') ->setPlaceholder('Enter user email address...') ->setType(SpotlightCommandDependency::INPUT) ); } // Search method for 'team' dependency public function searchTeam(string $query) { return Team::where('name', 'like', "%{$query}%") ->limit(10) ->get() ->map(function (Team $team) { return new SpotlightSearchResult( $team->id, $team->name, sprintf('Team with %d members', $team->users_count) ); }); } // Search method for 'role' dependency - has access to resolved 'team' public function searchRole(string $query, Team $team) { // Scoped search: only show roles available for selected team return $team->availableRoles() ->where('name', 'like', "%{$query}%") ->get() ->map(function (Role $role) { return new SpotlightSearchResult( $role->id, $role->name, $role->description ); }); } // Execute receives all resolved dependencies public function execute(Spotlight $spotlight, Team $team, Role $role, string $email): void { // Emit event to open a modal with pre-filled data $spotlight->dispatch('openModal', 'create-user-modal', [ 'team_id' => $team->id, 'role_id' => $role->id, 'email' => $email, ]); } } ``` ## Conditional Command Visibility Control when commands appear in Spotlight using the `shouldBeShown` method or conditional registration. ```php // app/Spotlight/AdminDashboard.php redirect('/admin'); } // Only show to users with admin permission public function shouldBeShown(Request $request): bool { return $request->user()?->can('access-admin-dashboard') ?? false; } } ``` ```php // app/Providers/AppServiceProvider.php environment('local'), DevTools::class ); // Register unless condition is true Spotlight::registerCommandUnless( app()->isProduction(), \App\Spotlight\DebugMode::class ); } } ``` ## Toggling Spotlight Programmatically Open or close Spotlight from Livewire components, Alpine.js, or JavaScript. ```php // In a Livewire component (v3) dispatch('toggle-spotlight'); } public function render() { return view('livewire.search-button'); } } ``` ```html ``` ## SpotlightSearchResult Create search results for dependencies with optional synonyms for fuzzy matching. ```php id, // Unique identifier name: $user->name, // Display name description: $user->email // Secondary text ); // Search result with synonyms for better matching $result = new SpotlightSearchResult( id: $product->id, name: $product->name, description: $product->category, synonyms: [ $product->sku, $product->brand, ...$product->tags->pluck('name')->toArray(), ] ); ``` ## SpotlightCommandDependency Types Define dependencies as searchable lists or free-text input fields. ```php setPlaceholder('Search for a team...') ->setType(SpotlightCommandDependency::SEARCH); // INPUT type: Free-text input field $nameDependency = SpotlightCommandDependency::make('name') ->setPlaceholder('Enter the new project name...') ->setType(SpotlightCommandDependency::INPUT); ``` ## Customizing Translations Publish and customize the translation files to change the placeholder text. ```bash php artisan vendor:publish --tag=livewire-ui-spotlight-translations ``` ```php // resources/lang/vendor/livewire-ui-spotlight/en/spotlight.php 'Search commands, navigate, or take action...', ]; ``` ## Bundling JavaScript Manually Disable automatic JS injection and bundle Spotlight's JavaScript with your application. ```bash npm install fuse.js ``` ```php // config/livewire-ui-spotlight.php return [ 'include_js' => false, // ... ]; ``` ```javascript // resources/js/app.js require('vendor/wire-elements/spotlight/resources/js/spotlight'); ``` ## Complete Command Example with All Features A comprehensive example demonstrating all available features of a Spotlight command. ```php // app/Spotlight/SearchAndViewUser.php add( SpotlightCommandDependency::make('department') ->setPlaceholder('Filter by department (optional, press Enter to skip)...') ) ->add( SpotlightCommandDependency::make('user') ->setPlaceholder('Search for a user by name or email...') ); } public function searchDepartment(string $query) { return Department::where('name', 'like', "%{$query}%") ->orderBy('name') ->limit(5) ->get() ->map(fn (Department $dept) => new SpotlightSearchResult( $dept->id, $dept->name, sprintf('%d employees', $dept->users_count) )); } public function searchUser(string $query, ?Department $department = null) { $usersQuery = User::query() ->where(function ($q) use ($query) { $q->where('name', 'like', "%{$query}%") ->orWhere('email', 'like', "%{$query}%"); }); if ($department) { $usersQuery->where('department_id', $department->id); } return $usersQuery ->limit(10) ->get() ->map(fn (User $user) => new SpotlightSearchResult( id: $user->id, name: $user->name, description: $user->email, synonyms: [$user->employee_id, $user->phone] )); } public function execute(Spotlight $spotlight, User $user, ?Department $department = null): void { $spotlight->redirectRoute('users.show', ['user' => $user->id]); } public function shouldBeShown(Request $request): bool { return $request->user()?->can('viewAny', User::class) ?? false; } } ``` ## Summary Wire Elements Spotlight provides a powerful command palette interface for Laravel applications. The primary use cases include quick navigation between application pages, executing common actions (logout, create records, toggle settings), searching and selecting database records through dependencies, and providing keyboard-first workflows for power users. Commands integrate with Laravel's service container, allowing type-hinted dependency injection in both the `execute` and `shouldBeShown` methods. Integration follows standard Laravel package conventions. Commands are registered either through the configuration file or programmatically in service providers. The package works seamlessly with Livewire v3, emitting events and redirecting users through the Spotlight component instance. For applications not using TailwindCSS, the package can inject its own styles. The frontend uses Alpine.js for reactivity and Fuse.js for fuzzy search, both of which can be bundled with your application's assets or loaded automatically.