nickperkins / blade-icon-picker
Standalone icon picker Blade component for Livewire forms
Requires
- php: ^8.2
- blade-ui-kit/blade-icons: ^1.0
- illuminate/support: ^10.0 || ^11.0 || ^12.0
- livewire/livewire: ^3.0 || ^4.0
Requires (Dev)
- blade-ui-kit/blade-heroicons: ^2.0
- orchestra/testbench: ^9.0 || ^10.0
- pestphp/pest: ^3.0
Suggests
- blade-ui-kit/blade-heroicons: Provides Heroicons for the icon picker
README
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" />
Installation
composer require nickperkins/blade-icon-picker
composer require blade-ui-kit/blade-heroicons # recommended default icon pack
Publish the assets:
php artisan vendor:publish --tag=icon-picker-assets
Include 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.
Usage
Basic
<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.
Custom placeholder
<x-icon-picker::icon-picker wire:model="icon" :value="$icon" placeholder="Choose a menu icon" />
Disabled
<x-icon-picker::icon-picker wire:model="icon" :value="$icon" disabled />
Livewire form example
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>
Features
- 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
Dark mode
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 */ } }
Theming
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.
No icon packs installed?
The component renders a helpful message telling the developer to install blade-ui-kit/blade-heroicons.
Requirements
- PHP 8.2+
- Laravel 10, 11, or 12
- Livewire 3
- blade-icons 1.0+
Acknowledgments
Inspired by lukas-frey/filament-icon-picker, which demonstrated that an icon picker is a valuable UX pattern for Livewire forms.
License
MIT