nickperkins/blade-icon-picker
A standalone icon picker Blade component for Livewire forms that works with any blade-icons pack, featuring search, lazy rendering, keyboard navigation, and responsive styling with no Tailwind dependency.
Architecture fit. The package is a Blade component wrapping an Alpine.js island, not a Livewire component. That single decision determines where it fits. On render, the server enumerates registered blade-icons sets and hands the browser a catalog; the browser owns search, filtering, lazy chunking, and keyboard navigation, and the only server round-trip on selection is $wire.set(). For a Laravel 10–13 + Livewire 3/4 + blade-icons application, this is a clean, low-coupling fit that avoids per-keystroke wire:model.live search cost. It is a poor fit for Livewire 2, Inertia/Vue/React forms, or any UI where Alpine is not already present — the coupling becomes dead weight.
The strongest architectural property is interoperability of the persisted value. The stored string (e.g. heroicon-o-home) follows the blade-icons ID convention consumed by @svg(), svg(), and Filament, so the data written to the database remains valid if the picker UI is later swapped or removed. That is the main reason this is a low-regret adoption and the argument to lead with in a design review.
Integration feasibility. Requirements are mainstream and low-friction: PHP 8.2+, Laravel 10–13, Livewire 3/4, blade-icons 1.0+. Install is composer require, one tagged asset publish, and two manual <link>/<script> tags — no service-provider configuration, migrations, queues, or external services. Nothing here needs platform change approval beyond a routine dependency review.
Technical risk, ranked:
prefers-color-scheme and then says it is supported automatically; theming examples reference .icon-picker-root while the dark-mode section references .ip-root; the README lists Laravel 10–12 / Livewire 3 while the v1.0.0 release notes list Laravel 10–13 / Livewire 3 or 4; the description contains a "Lightwire 3" typo. v1.1.0 shipped AJAX-based icon loading with set/variant filtering that is not documented in the README at all — the docs lag the code, which is the highest-signal maturity indicator here.wire:model alone does not seed the initial value; :value="$icon" is mandatory. Developers will ship a picker that silently fails to redisplay a saved icon. Validation and error display are entirely the host app's responsibility.x-html/innerHTML) and Alpine inline expressions interact with strict CSPs, and a second Alpine instance on the page is a known conflict class.Key questions for engineering and the maintainer
:value holds a stale or unregistered icon ID (renamed/removed pack)? Silent blank, exception, or graceful fallback?x-html/innerHTML, and is that compatible with our CSP (no unsafe-inline)?Stack fit. Adopt only where the target is Laravel 10–13 + Livewire 3/4 and blade-icons is already present or an easy yes. Tailwind is not required — the standalone CSS is a genuine advantage for admin panels living outside the main design system. If the form layer is Vue/React/Inertia or Livewire 2, stop.
Migration path. Low risk in both directions because the stored value is blade-icons-native:
<select> of icon names, or a hand-rolled grid: the column already holds (or can be backfilled to) a blade-icons ID, so no schema change is required — only the form field is swapped.lukas-frey/filament-icon-picker: same underlying ID convention, so the value format survives; only the UI dependency changes.Compatibility checks before committing. Confirm PHP/Laravel/Livewire versions in composer.json against ours; confirm an installed blade-icons pack (add blade-ui-kit/blade-heroicons if not); confirm the deploy pipeline permits and commits published assets with cache-busting; confirm CSP allows inline SVG and Alpine inline expressions; resolve the dark-mode contract (ip-dark class vs [data-theme] attribute) against our actual theme mechanism in a spike rather than from the README.
Sequencing.
<x-app.icon-field>) that enforces the wire:model + :value pairing, renders the error slot, and binds the theme class. No product developer calls the vendor tag directly. This is the single highest-value integration step and the one that keeps support cost flat.Maintenance. Assume we own this, not the upstream author. Pin a version, commit the published dist assets so deploys do not depend on re-publishing, and document a fork decision point. Budget a recurring allowance for dependency bumps tied to Laravel and Livewire major releases. The internal wrapper partial is what absorbs version churn — upgrade the wrapper, not N call sites.
Support. No SLA, no support policy, no dependents, no issue-tracker history to lean on. First-line support is our own team. Two documentation defects (dark mode, selector naming) will generate recurring questions from front-end developers who copy examples without testing; write a short internal usage note in the wrapper's README that supersedes upstream docs, and link it in code review guidance.
Scaling. Two axes matter. Breadth: cost scales with the number of forms using the picker until the wrapper exists; after that, marginally. Page weight: cost scales with the number of icon packs installed and the number of pickers per page. Enforce pack allow-listing at the wrapper level (and confirm whether v1.1.0's set/variant filtering gives us a lever), and avoid placing a picker on high-traffic public pages — admin and configuration surfaces only.
Failure modes to plan for.
wire:navigate re-init → picker initializes once and dies after navigation. Mitigation: explicitly test SPA-style navigation in the spike.Ramp-up. Minimal. A mid-level Laravel developer can be productive in under an hour given working examples; deep familiarity (AJAX endpoint, catalog discovery, theme contract) takes roughly half a day. The wrapper partial means most developers never touch the vendor API. Documentation debt — not code complexity — is the real ramp-up cost, so the internal note is doing more load-bearing work than usual for a package this small.
How can I help you explore Laravel packages today?