Product Decisions This Supports
- Form UX roadmap bet: "bulk selection in 10 minutes, not a sprint." Any surface with
ChoiceType(multiple: true) — admin filters, permission/role grids, tag pickers, export column pickers, category multi-assign — can ship a "Select all" affordance as a per-field option rather than a bespoke JS ticket. This converts a recurring low-value feature request ("can we add select-all here too?") into a one-line form-type flag.
- Build vs buy: buy (fork-friendly). The problem is small, solved, MIT-licensed, and genuinely boring — a checkbox plus a Stimulus controller. Building in-house costs ~1–3 dev-days per form plus ongoing maintenance across every template; adopting costs an attribute. The real decision is not "build vs buy" but "consume vs vendor" — see risk notes below.
- Architecture decision it validates: frontend-driven, backend-declared. The bundle does not generate HTML server-side for the toggle; it marks the field and ships config through
data-* attributes, and a Stimulus controller does the rest. That is the right shape for this problem and keeps the PHP surface tiny. It also means adoption is cheap to reverse: remove the option, keep your templates.
- Segments most likely to benefit: internal admin/back-office tools (EasyAdmin-style CRUD, permission matrices), B2B filter panels with 10–100 options, and any product area where users batch-apply a setting ("set all regions to read-only"). Low value for consumer-facing forms with 3–5 options.
- Roadmap signal to capture: whether multi-select friction shows up in support tickets, task-completion time, or abandonment on filter screens. If it does, this is a cheap instrumented experiment — you can A/B the option on one form and measure time-to-selection and "all options selected" events.
- Portfolio-level decision: treat this as a pattern adoption (one shared Stimulus controller across the app) rather than a per-form hack. Standardizing now prevents five hand-rolled "select all" implementations with five different a11y behaviours later.
When to Consider This Package
Consider it when all of these hold:
- The application is Symfony 6/7/8 — note explicitly: despite being scoped under a "Laravel/PHP" heading, this is a Symfony bundle. It is not usable in Laravel without rebuilding the concept (Livewire/Alpine or a Blade partial would be the equivalent). If your stack is Laravel, stop here and re-evaluate a JS-only alternative.
- Forms are authored with Symfony's Form component using
ChoiceType with multiple: true — that is the only integration point.
- The frontend already runs Stimulus (Symfony UX / AssetMapper or Webpack Encore). Adding a second JS paradigm for a checkbox is not worth it.
- You need the behaviour in multiple places or expect to; a single field is a 20-line inline script.
- You accept progressive enhancement loss: with JS disabled or before the controller boots, there is no select-all. Confirm that is acceptable for your audiences (public-sector/enterprise accessibility requirements may not allow it).
- You are comfortable with single-maintainer, zero-star, zero-dependent supply chain risk and can own a fork if needed.
Look elsewhere (or build ~40 lines yourself) when:
- You need guaranteed, tested accessibility (indeterminate tri-state, roving focus, screen-reader announcements, WCAG 2.2 AA sign-off). Verify the controller's
aria-checked/indeterminate handling yourself — do not assume it.
- You rely on Turbo/Turbo Streams, htmx, Livewire, or partial re-renders. The controller must re-initialize on DOM replacement and reconcile checkbox state after a validation-error re-render. Test this before committing; it is the most common failure mode for "frontend-driven" bundles.
- You need i18n of the toggle label, or a specific design-system component (Bootstrap/Tailwind/Shadcn) with mandated markup.
- Your choices are async-loaded (chosen.js / TomSelect / AJAX-populated). A new option added after boot will not be covered unless the controller observes mutations.
- You want vendor SLA, security policy, or active triage. No stars/dependents means no community backpressure; treat the release date as the only maintenance signal you have and check the commit history yourself.
- The bundle's Symfony/PHP version floor does not match your oldest supported app — check
composer.json rather than trusting the README.
Adoption criteria (run before the spike): confirm the exact form-type option name and default; confirm the Stimulus controller is registered via a documented mechanism (UX Flex recipe vs manual controllers.json); write one integration test on your own form type; and smoke-test expanded-checkbox, collapsed-select, post-validation-error, and Turbo-navigation cases.
How to Pitch It (Stakeholders)
For executives (30 seconds). We can close a recurring, low-glamour usability gap — users manually ticking 40 checkboxes — with a free, MIT-licensed add-on that is one option on an existing form field. Cost is a short spike, not a sprint; no new infrastructure, no data model change, no migration, and it is trivially reversible. The trade-off is honest: it is a small, single-maintainer open-source package with no adoption yet. We mitigate that by vendoring/forks if it becomes load-bearing, and by keeping our usage shallow so removing it costs hours. Recommendation: pilot on one high-traffic admin form, measure, then standardize — not a company-wide mandate on day one.
For engineering (the ask).
- Effort: ~half a day. Register the bundle, enable the Stimulus controller through the existing UX/AssetMapper pipeline, add the field option to 1–2 form types, ship a test.
- Blast radius: near zero. The PHP side only sets an option and emits
data-* attributes; the toggle is created in the browser. No template rewrites, no DB changes, no public API changes.
- What we own: the a11y contract (indeterminate state, keyboard behaviour, label text/i18n), and re-initialization under Turbo/partial reloads and after failed validation. Both are on us to verify, not on the package.
- Guardrails: pin the version in
composer.json; add one contract test asserting the field renders the expected data attributes so an upstream change fails loudly; keep our own Stimulus controller wrapper thin so a swap-out is a single-file change. If we standardize beyond two forms, fork it into an internal package we control.
- Decision gate: if the pilot shows no measurable improvement in time-to-selection or a11y review flags issues, we drop it and keep the pattern in-house — sunk cost is under a day.