jeffersongoncalves/filament-flux
Filament v5 plugin that brings Livewire Flux UI components into your admin panel as native Form Fields, Table Columns, Infolist Entries, and Actions. Includes an install command that patches your panel theme CSS automatically.
This package is a UI-translation layer, not a new abstraction. It does not ask you to learn a new API — it makes Flux markup render behind Filament's existing component classes. That framing determines the whole onboarding path: install it, then flip switches at increasing blast radius until something breaks, then flip that one switch back.
Prerequisites. Filament ^5.0, Laravel ^11–^13, PHP ^8.2, Livewire ^4.0, Flux ^2.14. The package is 1.x only and tracks Filament v5 — there are no v3/v4 backports, so this is a non-starter on any existing v4 panel. Note that Flux here means the free tier; <flux:modal> is not available, which the README calls out explicitly and which shapes the Actions API (see below).
Install, in order. The order matters — the installer patches a theme file that must already exist:
composer require jeffersongoncalves/filament-flux
php artisan make:filament-theme admin # must run first
php artisan filament-flux:install --panel=admin
npm run build
The filament-flux:install command is idempotent: it appends the Flux and package stylesheet @imports to resources/css/filament/{panel}/theme.css and won't duplicate them on re-run. That makes it safe to run again after composer update or when standing up a second panel.
Register the plugin in your panel provider:
public function panel(Panel $panel): Panel
{
return $panel->plugins([
FilamentFluxPlugin::make(),
]);
}
At this point nothing visible has changed. The plugin registers view-namespace hints and a theme-switcher JS bridge, but every toggle defaults to off. That is the correct first milestone: the panel should boot identically to before.
Where to look first. Open FilamentFluxPlugin and read the four builder methods — useEverywhere(), useFluxNavigation(), useFluxComponents(), and the three constructor options (scopeClass, injectAppearance, injectScripts). Those four calls are the entire public surface of the package. Everything else is per-component flux*() methods.
First use case. Don't start with useEverywhere(). Start by swapping exactly one field in one Resource on one panel:
FluxInput::make('email')->email()->required();
Load the form. If the input renders with Flux styling, your theme.css and npm run build are wired correctly and you can proceed to the bulk toggles with confidence. If it renders unstyled or looks like a plain Filament input, the problem is almost always CSS (see Gotchas), not the plugin.
The escalation ladder. Adopt in this order, shipping between each step:
FluxInput / FluxAction / FluxBadgeColumn instances in new code.useEverywhere() — the bulk swap of native Filament form fields for Flux subclasses.useFluxNavigation(['sidebar' => true]) — sidebar only.useFluxComponents([...]) — opt-in Blade atoms, slug by slug.shell, themeSwitcher, topbar — the invasive tail.Each rung is independently reversible via a one-line config change, so treat them as feature flags, not a migration.
useEverywhere() is the highest-leverage call, and the reason to consider this package at all. Your existing Resources keep calling TextInput::make(), Select::make(), Toggle::make() — they receive the Flux subclass automatically. Zero code changes across a large codebase. The subclasses extend the Filament natives, so autocomplete(), mask(), revealable(), length(), searchable(), relationship() all keep working; only the rendered markup changes.
The opt-out map is keyed by slug, so you disable the fields whose Filament-only behaviour you actually depend on rather than rewriting them:
FilamentFluxPlugin::make()->useEverywhere([
'select' => false, // keep client-side searchable <select>
'otp' => false,
]);
Practical opt-out heuristic: select (searchable/relationship UX), otp (paste and auto-advance behaviour), and checkboxList (bulk-select affordances) are the three people most often turn back off. Start with them disabled, then re-enable one at a time to see whether Flux's version is acceptable.
Actions: keep Filament's modal machinery. FluxAction and FluxDropdown are styling wrappers, and requiresConfirmation() delegates to Filament's native modal. This is a design constraint (no <flux:modal> in free Flux) but also a blessing — confirmation flows, form-in-modal actions, and Action Groups keep behaving exactly as your team already knows:
FluxAction::make('publish')
->fluxVariant('primary')
->fluxIcon('rocket-launch')
->fluxKbd('cmd+enter')
->fluxLoading()
->requiresConfirmation()
->action(fn (Post $record) => $record->publish());
Data-driven colour and icon state. The column and infolist components accept closures for fluxColor() and fluxIcon(), plus the array form for per-value maps. This is where Flux pays off visually — status pills and avatars that read well at a glance:
FluxBadgeColumn::make('status')
->fluxColor(['draft' => 'zinc', 'published' => 'lime', 'archived' => 'red'])
->fluxIcon(fn ($state) => $state === 'published' ? 'check-circle' : null)
->fluxBadgeVariant('pill');
fluxColor() resolves three forms — a string, a state→colour array, or a closure — so use the array for enumerable states and the closure for derived logic ($record->user->is_admin ? 'blue' : 'zinc').
Custom Pages get the Flux feel via toasts, not notifications. The notifications slug only swaps the toast group envelope; each Notification keeps Filament markup inside. If you want genuine Flux toasts on a custom page, dispatch through the provided FluxToast component and add <x-flux::toast.group> to your panel layout's body.start render hook. Leave the user menu on Filament — it's the most flexible affordance for tenants, profile links, and dynamic items, and the README explicitly recommends keeping it.
Theme switching is bridged, not replaced. The plugin installs a JS bridge so Filament's theme-changed event and flux.appearance stay in sync, including cross-tab via storage events. themeSwitcher => true swaps the three-button control for a <flux:dropdown> menu but still dispatches theme-changed, so any existing dark-mode listener you have keeps firing. Build dark mode once, in Filament's system, and let the bridge mirror it.
Mixed icon sets are handled. If your project registers Font Awesome, Tabler, Lucide, or similar via Blade Icons, HeroiconNormalizer detects the known prefixes and falls back to generate_icon_html(). You don't need to audit every icon string before enabling useFluxComponents(['icon' => true]) — but do spot-check a page that uses each icon family.
Styling failures are almost always CSS, not PHP. If Flux components render unstyled: re-run php artisan filament-flux:install --panel=admin (idempotent, safe), confirm all three @import lines are present and in order in theme.css, then npm run build. Tailwind v4 scans the vendor Flux and package directories from those imports — a stale build cache after composer update is the single most common cause of "it worked yesterday."
View-namespace overrides are the real risk surface, and they fail silently. The plugin prepends hint paths to the filament, filament-schemas, filament-widgets, and filament-notifications namespaces; missing files fall back to vendor copies. That's a deliberate upgrade-safety mechanism — but it means an override that no longer matches the active Filament minor's prop signatures degrades to Filament markup rather than throwing. When something "didn't take," inspect the rendered markup for Filament's classes before touching your own code. The overrides that matter are sidebar item, sidebar group, topbar item, layout index, and livewire sidebar.
shell is the most invasive toggle in the package. It rewrites the panel's outer <aside> into <flux:sidebar> and wraps content in <flux:main>, including the sidebar Livewire view. Enable it last, on a panel with few customizations, and walk every render hook, the tenant menu, global search, logo, and footer before trusting it. The README's guidance — the Filament version shipping with each release is the verified one — means pinning matters: treat a Filament minor bump as a reason to re-test the navigation and Blade-component slugs.
Slug names don't always match class names. The useEverywhere() map uses radio and checkboxList, while the documented components are FluxRadioGroup and FluxCheckboxGroup. Don't assume ['radioGroup' => false] will do anything — an unrecognised key is silently ignored, so verify the opt-out actually took by inspecting the rendered markup. Same caution for iconButton vs. anything else you'd guess.
Known feature loss per slug — disable rather than fight it. pagination drops pageOptions (the per-page dropdown), extremeLinks, and cursor-paginator chevron handling. Badge overrides don't fully map delete buttons, deferred badges, or key bindings. section doesn't cleanly cover secondary/divided/aside variants. dropdown loses loading indicators and form-tag items. If a screen depends on those, set that single slug to false and keep Filament's version — the plugin is designed for exactly that.
Don't disable injectAppearance / injectScripts casually. They control @fluxAppearance in <head> and @fluxScripts before </body>. Turning them off means you own those directives in your layout; if you forget, Flux components lose their appearance bootstrapping and dark mode flickers or sticks. Keep both on unless you have a documented reason.
Use scopeClass() deliberately. Every Flux page gets a wrapper class by default. If your own CSS targets Flux internals and you're seeing specificity fights, change the scope class rather than reaching for !important; pass null to disable the wrapper entirely, but only after confirming nothing in your stylesheets assumed its presence.
Caching bites after config changes. Plugin toggles change which views are resolved. After editing the panel provider, clear view:cache and Filament's component cache, or you will debug a problem that no longer exists.
On maturity. Fourteen stars, zero dependents, first release mid-2026, and it targets a Filament major that is itself new. The upside is that the API is small and the toggles are granular enough to keep you safe. The downside is that you are an early adopter of view overrides tied to a specific Filament minor — budget for re-verification on every composer update, read the changelog per release, and pin both filament/filament and this package together. Adopt it panel-by-panel and new-code-first, and it's a low-risk way to get Flux's visual language without rewriting a single Resource.
How can I help you explore Laravel packages today?