A standalone icon picker Blade component for Livewire forms. Works with any blade-icons pack — Heroicons, Font Awesome, or custom sets.
<x-icon-picker::icon-picker wire:model="icon" :value="$icon" />composer require nickperkins/blade-icon-picker
composer require blade-ui-kit/blade-heroicons # recommended default icon packPublish the assets:
php artisan vendor:publish --tag=icon-picker-assetsInclude the JS and CSS in your layout:
<head>
<link rel="stylesheet" href="{{ asset('vendor/icon-picker/icon-picker.css') }}">
{{-- ... --}}
</head>
<body>
{{-- ... --}}
<script src="{{ asset('vendor/icon-picker/icon-picker.js') }}"></script>
{{-- Must come AFTER Alpine.js --}}
</body>In Livewire 3, the JS auto-registers with Alpine — no manual Alpine.data() call needed.
<x-icon-picker::icon-picker wire:model="icon" :value="$icon" />Important: Pass both wire:model (for write-back) and :value="$icon" (for initial/redisplay). This is required because the component is a Blade component, not a Livewire component.
<x-icon-picker::icon-picker
wire:model="icon"
:value="$icon"
placeholder="Choose a menu icon"
/><x-icon-picker::icon-picker
wire:model="icon"
:value="$icon"
disabled
/>use Livewire\Component;
class CreateMenu extends Component
{
public string $icon = '';
public function rules(): array
{
return ['icon' => ['required', 'string']];
}
public function render()
{
return view('livewire.create-menu');
}
}<form wire:submit="save">
<x-icon-picker::icon-picker wire:model="icon" :value="$icon" />
@error('icon')
<p class="text-red-500">{{ $message }}</p>
@enderror
<button type="submit">Save</button>
</form>- Search: Substring token matching — type
ar leto findArrow Left - Lazy rendering: Icons render 30 at a time as you scroll
- Keyboard navigation: Arrow keys, Enter, Escape
- Responsive grid: 4 columns on mobile → 12 on desktop
- Any blade-icons pack: Heroicons, Font Awesome, custom — all auto-discovered
- Standalone CSS: No Tailwind dependency; override colors with CSS custom properties
The component ships dark-mode variables but does not auto-detect prefers-color-scheme — that’s your app’s job. Activate dark styles by adding the ip-dark class to the component or any ancestor, or by using a [data-theme="dark"] attribute on a parent element.
{{-- Follow a data-theme attribute on <html> (no extra markup needed) --}}
{{-- In your CSS: [data-theme="dark"] .ip-root { } is already handled --}}
{{-- Or apply ip-dark directly --}}
<x-icon-picker::icon-picker
wire:model="icon"
:value="$icon"
class="ip-dark"
/>If you want to mirror the OS preference, add it yourself:
@media (prefers-color-scheme: dark) {
.ip-root { /* your app's dark scope */ }
}Override the CSS custom properties anywhere in your stylesheet:
.icon-picker-root {
--ip-primary: #dc2626;
--ip-bg: #fef2f2;
}Dark mode is supported automatically via prefers-color-scheme.
The component renders a helpful message telling the developer to install blade-ui-kit/blade-heroicons.
- PHP 8.2+
- Laravel 10, 11, or 12
- Livewire 3
- blade-icons 1.0+
Inspired by lukas-frey/filament-icon-picker, which demonstrated that an icon picker is a valuable UX pattern for Livewire forms.
MIT