williamug/searchable-select
A feature-rich searchable dropdown component for Laravel Livewire 3 & 4, built with Alpine.js and Tailwind CSS. Supports real-time search, multi-select with tags, grouped options, dark mode, full keyboard accessibility, and cascading dependent dropdowns.
Architecture fit. williamug/searchable-select is a Blade component package, not a domain library. It ships a view-layer abstraction (<x-searchable-select>) that wraps Alpine.js client-side filtering around a wire:model-bound property, with an internal $wire.entangle() bridge. That places it squarely in the presentation tier of a Livewire 3/4 application: no service container bindings beyond a view-provider registration, no middleware, no persistence, no queued work, no external API surface. For a TPM, this is a favorable shape — the integration boundary is narrow and reversible. The constraint is that it presumes an existing Livewire + Tailwind stack; there is no React/Vue/Inertia path, and no server-side search endpoint for large option sets.
Integration feasibility. Low ceremony. composer require auto-registers the provider; usage is a single tag with :options and wire:model. The real integration work is in build tooling, not application code: Tailwind must be told to scan the package's Blade views or the component renders unstyled/invisible. That means either an @source directive (Tailwind v4) or a content glob (v3) plus an asset rebuild. This is a one-time, well-documented step, but it is a hard failure mode if missed — and it fails visually, not at build time, so it can slip past CI into a staging demo.
Technical risk. Overall low-to-moderate, concentrated in three areas rather than in the code itself:
Model::all() in mount(). That is fine at hundreds of rows and pathological at tens of thousands — the payload rides the Livewire snapshot into every request. There is no documented server-side/async search mode. This is the single largest architectural caveat and should be a go/no-go gate per form.Key questions.
$wire.entangle() interact acceptably with our existing validation, dirty-state tracking, and wire:model modifiers (.live, .defer) policy?Stack fit. Acceptable only for teams already standardized on Laravel 11–13 + Livewire 3/4 + Tailwind. For anyone else, the cost of adopting the stack exceeds the value of the component; the correct answer is to build an equivalent in-house rather than adopt this. Within a Livewire/Tailwind estate it slots in with no architectural negotiation.
Migration path. Adoption is additive and per-field, not a framework decision. The recommended path is: pilot on one low-traffic internal form (e.g., an admin filter or profile settings page), validate the Tailwind scan configuration in the real build pipeline, then expand form-by-form. Retrofitting an existing <select> is a markup swap plus a prop mapping (option-value / option-label) — cheap to do, cheap to undo. Do not announce it as a house standard; let it earn that by surviving a release cycle.
Compatibility. Three compatibility surfaces must be closed before any pilot merges:
@source/content entry must be committed alongside the first usage, and the CI asset build must be re-run and diffed. Prefer verifying in CI (a snapshot or visual check) rather than relying on a developer noticing missing styles.Sequencing. (a) Confirm the option-count ceiling per candidate field; (b) run the pilot with the Tailwind config committed; (c) add regression tests around dependent-dropdown cascade behavior — the updatedPropertyName() reset pattern is application logic we own, not package logic, and it is where bugs will live; (d) publish views (--tag=searchable-select-views) only if we actually need to diverge, since a published view is a fork we maintain; (e) formalize an approval gate for expansion to customer-facing forms.
Maintenance. Near-zero ongoing cost at the application layer, but nonzero at the platform layer: the Tailwind scan entry becomes a permanent build-config obligation that a future refactor can silently break. Because we will almost certainly vendor or fork, assign a named owner. Budget roughly the effort of maintaining a small internal UI component — but with the added overhead of tracking upstream, which has little activity to track.
Support. Effectively self-support. Zero dependents and 2 stars mean no Stack Overflow corpus, no community triage, no third-party writeups. Internal engineers will be reading the Blade source to answer questions. That is acceptable precisely because the source is small and readable — but it should be priced in during ramp-up, not discovered during an incident. Security posture likewise rests on the MIT source being auditable rather than on an upstream response process.
Scaling. Two distinct axes. Traversal scale (number of forms using it) is essentially free — it is a stateless view component with no runtime footprint. Data scale is the real ceiling: client-side filtering plus whole-collection hydration will degrade Livewire payloads and first-paint latency as option counts grow. Set a documented threshold (a few hundred options is comfortable; low thousands is the point to revisit) and route larger sets to a different pattern. Multi-select with many selections also increases snapshot size per request — worth watching on high-frequency forms.
Failure modes. Ranked by likelihood and blast radius:
| Failure | Likelihood | Impact | Detection |
|---|---|---|---|
| Tailwind purge strips styles → invisible/ugly dropdown | High on first integration | High (appears broken to users) | Visual QA / CI asset diff |
Model::all() on a large table → slow page, fat payloads |
Medium | Medium–High | Query count and payload review |
| Livewire 3 vs 4 behavioral drift on entangle | Low–Medium | Medium | Pilot regression tests |
| Upstream abandonment / no security response | Low near-term | Low (forkable, small surface) | Dependency review cadence |
| Dependent-dropdown state desync (stale child selections) | Medium | Medium | Test the updated* reset logic explicitly |
Ramp-up. Short for developers — the prop table is complete and the examples (basic, multi-select, cascading, grouped) cover the main shapes, so a mid-level Livewire developer is productive in well under a day. The real ramp-up cost sits with platform/DevOps, who must understand and preserve the Tailwind source-scan configuration, and with QA, who must know that style regressions here present as missing CSS rather than as exceptions. Given the low score and zero dependents, the honest TPM framing is: viable tactical convenience for a Livewire/Tailwind shop, contingent on a one-form pilot, an explicit option-count ceiling, and a named owner for the fork — not a component to standardize on before it has survived a release cycle in our own codebase.
How can I help you explore Laravel packages today?