symfony/ux-toolkit
Symfony UX Toolkit offers shared utilities and conventions for building Symfony UX packages, simplifying frontend integration and reducing boilerplate when wiring JavaScript components into Symfony applications.
symfony/ux-toolkit is a Symfony UX / Twig component kit (Shadcn-style, Radix-inspired markup + Stimulus controllers). If you are working in a pure Laravel app, read this assessment as a reference-and-port exercise: the markup, Tailwind class strings, and behavioral contracts map almost 1:1 onto Livewire/Flux or Alpine components, but there is no Blade integration. If your monorepo has a Symfony app alongside Laravel, this is directly installable there.
Minimal steps (Symfony host):
composer require symfony/ux-toolkitphp bin/console ux:install and pick a recipe. Start with button, then toast.templates/components/ — the installed Twig components (your real source of truth)assets/controllers/ — the Stimulus controllers driving behavior#3947) — browse components/recipes before installing rather than installing blind.First real use case: install the toast recipe (#3902), drop <twig:Toast …> (or the recipe's helper) into your layout, and trigger a toast from a controller. That gives you a fast read on how recipes, controllers, and Tailwind classes hang together before you commit to a bigger install like combobox or command.
For Laravel devs: the fastest way to get value is to install the kit in a throwaway Symfony app (or the preview app), then copy the markup and port the Stimulus controller logic to Alpine/Livewire. The command and context-menu recipes added in 3.6.0 are the two most-requested patterns in Laravel apps (⌘K palette, right-click menus), so they are worth reading even if you never install the package.
Recipe-driven scaffolding. Everything is a recipe: button, dialog, sheet, drawer, dropdown-menu, combobox, select, input-group, toast, command, context-menu, navigation-menu, menubar, resizable, questionnaire, pagination, breadcrumb, alert-dialog, tooltip, date-picker. ux:install copies files into your app; from that point they are yours to edit. Treat the installed templates as vendored code — you own the diff.
Diff-then-overwrite flow (3.6.0). ux:install now shows a diff before overwriting (#4019) and correctly overwrites files newer than the recipe (#4018). Practical workflow: commit everything, run ux:install to pull recipe updates, review the diff, then accept. This is the closest thing the package has to an upgrade path for already-installed components.
Compound components with data-slot. Components follow the Shadcn convention of data-slot markers for styling hooks and testability. 3.6.0 fixes data-slot being shadowed when forwarded to a child (#3905) — if you keyed CSS or tests off slot names, re-verify after upgrading.
DOM-move-safe components. The bulk of 3.6.0 is a coordinated set of fixes for components breaking once moved in the DOM (#4026–#4032, #4027, #4029, #3956). This matters enormously for Laravel devs, because Livewire wire:model updates, Turbo morph, and any morphdom-style swap move nodes constantly. If you are porting these behaviors to Alpine/Livewire, read those PRs — they encode the teardown/re-init contract you need (re-bind listeners on connectedCallback, don't rely on initial DOM position, re-measure portals on move).
Portal/overlay management. Dialogs, sheets, drawers, popovers, and menus all use portal-style overlays. 3.6.0 tightened this considerably: closed sheets and drawers are no longer keyboard-reachable (#3966, #3959), alert dialogs no longer open on load (#3955), dialogs regain modality after a DOM move (#4030–#4032), and the dialog trigger's aria-expanded stays in sync (#3958). The pattern to copy: a single overlay manager that owns inert/focus-trap state and is re-entrant on mount.
Upstream Shadcn alignment. select (#3910), input-group (#3938), and combobox (#3906) were re-aligned to the upstream Shadcn reference, plus a kit-level alignment to the Nova reference (#4061). If you are porting class strings to a Laravel/Tailwind app, take the post-3.6.0 markup — the previous versions drift from what you'll find in Shadcn docs.
Accessibility as a first-class contract. aria-label is now forwarded correctly through pagination, breadcrumb, and questionnaire (#4058); modals have an accessible name (#3952); tooltips stay in-viewport and fit their text (#4023); date pickers focus a day rather than "Previous month" (#3957); disabled sliders/accordions stop swallowing keyboard input (#3967, #3954). Use these as the acceptance criteria when you port components — they are a free a11y spec.
Kit pinning for GitHub-sourced kits. #4074 fixes kits pinned to a tag prefixed with v. If you reference kits by git ref in config, verify your ref string still resolves.
php artisan commands or resources/views/components. This is Symfony Console + Twig. Budget accordingly: the value is the markup and behavior contracts, not drop-in install.ux:install can now overwrite files that are newer than the recipe (#4018). That is the correct behavior but it will surprise you. Always run it on a clean working tree and read the new diff output (#4019) before confirming.wire:ignore hacks) for the DOM-move bugs, remove them or you'll double-bind.data-slot shadowing fix may change your DOM. Attribute forwarding (#3905) means the attribute now lands where Shadcn expects. If you styled [data-slot="…"] against the old, shadowed output, expect selector misses.#4041 fixes the kit linter crashing on Twig 4 — the linter was the blocker, not the components. Pin your Twig constraint deliberately rather than floating.#3950) plus new visual tests for recipes (#3948) is not useful to consumers directly, but it does tell you the project now has screenshot coverage — so behavior regressions should be rare between minors.#3947: kit preview assets + preview app shipped). Spin it up before installing anything; it is much cheaper than installing combobox + command + toast just to evaluate them.How can I help you explore Laravel packages today?