martin6363/filament-sidebar-resize
A lightweight Filament plugin that makes the admin sidebar resizable. Drag to adjust width, with configurable limits for a smoother, more flexible panel layout and better use of screen space.
What you're installing: a Filament v5 panel plugin that swaps the sidebar's fixed width for a drag-to-resize grip, writing the chosen width to localStorage and reapplying it on subsequent page loads. There is no database table, no migration, no server-side preference store, and no route. It is pure panel chrome.
Minimum viable install (≈15 minutes):
composer require martin6363/filament-sidebar-resize
php artisan vendor:publish --tag=filament-sidebar-resize-config # tag per README
php artisan filament:assets # publish the JS/CSS
Then register the plugin on the panel you actually want it on, in app/Providers/Filament/AdminPanelProvider.php:
public function panel(Panel $panel): Panel
{
return $panel
// ...
->plugin(\Martin6363\FilamentSidebarResize\FilamentSidebarResizePlugin::make());
}
(Class namespace and config tag are per the README — verify against src/ before pasting, since the package is at v1.0.1 and docs are thin. Read the plugin class first; it is a few dozen lines and tells you more than any README will.)
Where to look first, in order:
src/ — the Plugin class, the service provider, and how assets are registered (FilamentAsset::register(...) vs inline injection). This single fact determines your upgrade and deploy risk.config/filament-sidebar-resize.php — min/max width keys and defaults. This is the only knob you get.localStorage key it uses. You will need that key for debugging, resetting, and collision-checking in multi-panel apps.First real use case: an internal ops/back-office panel where users have long navigation labels (nested resources, translated labels in non-English locales) and the default sidebar truncates them. Install on one panel, pilot it for a week, and let the people who live in the panel all day tell you whether the affordance is discoverable before you roll it out everywhere.
Baseline: one panel, config-first. Set your bounds before anyone touches the grip. Pick a max that fits your smallest supported laptop viewport (a 600px sidebar on a 1366px screen leaves little table room). Choose a min that still renders your longest top-level label without clipping — otherwise the resize handle invites users to produce a broken layout. Publish config, set the values, then commit the config file to the repo.
Deploy script integration. Because the package ships assets, every deploy to a fresh environment needs the Filament asset publish step. Add it to your deploy pipeline alongside your other Filament publish commands, and re-run it on composer update of the package. A stale asset publish is the most likely cause of "works locally, grip missing in staging."
Feature-flag registration for a cheap kill switch. Registration is one line, so gate it:
->plugin(
config('features.sidebar_resize')
? FilamentSidebarResizePlugin::make()
: null
)
If a Filament upgrade breaks it, you flip an env var instead of hotfixing under pressure. Alternatively wrap it in ->when() on the panel or an env check inside the provider — the point is that removing it should never require a code review.
Pair it with the built-in sidebar controls, don't fight them. Filament already offers sidebarCollapsibleOnDesktop() and sidebarFullyCollapsibleOnDesktop(). Those govern collapsed state; the plugin governs expanded width. Decide explicitly whether the two coexist in your panel — a user who collapses the sidebar and later expands it should get their resized width back, not the default. Smoke-test the collapse/expand/refresh cycle.
Survive Livewire SPA navigation. Filament panels navigate via wire:navigate without a full page reload. The grip's JS must bind on each navigation (or delegate from document), and the stored width must be reapplied on each mount. If you see the sidebar snap back to default when clicking between resources, that's the bug — check whether the package listens for livewire:navigated.
Custom theme integration. If your panel uses a custom Filament theme, the grip's CSS lands in the same cascade as your fi-sidebar overrides. Write your width as a single CSS custom property on the sidebar so both the theme and the grip agree on one source of truth:
.fi-sidebar { width: var(--fi-sidebar-width, 20rem); }
Then verify the package's JS writes to that same property. If it doesn't, either align on it or accept two competing width declarations — the latter produces "resizes on drag but reverts on refresh" symptoms in whichever direction the cascade resolves.
Multi-panel and multi-tenant. The description claims multi-panel compatibility; verify it. If two panels share an origin, confirm the localStorage key is namespaced per panel (Filament panel ID). If it isn't, resizing the admin panel will silently resize the tenant/support panel too. For tenancy, test that switching tenants or switching panels doesn't reset or leak the width. If it leaks, the fix is trivial (namespace the key) but it's your fork at that point.
Give users a reset path. There is almost certainly no "reset to default" button. Either add one in your panel's user menu, or at minimum document that clearing site data restores the default. Without it, a user who drags the sidebar to 2000px on an ultrawide has no obvious way back on a laptop — they'll file a ticket.
Treat Filament upgrades as a re-validation gate. Add a checklist item to your Filament upgrade runbook: drag the grip, scroll the sidebar on a short viewport, open the mobile drawer, toggle dark mode, check RTL if you support it, switch tenants. Fifteen minutes, once per Filament bump. Because the failure mode is cosmetic and silent, it will never page anyone — it needs a named owner, not monitoring.
"Per-user" actually means per-browser. Width lives in localStorage, which is keyed by origin and browser profile, not by authenticated user. Consequences: it does not sync across devices, it doesn't follow the user to a new machine, it vanishes in incognito, and on a shared kiosk or a support desk with a common login, one person's 600px sidebar becomes everyone's. Set that expectation before someone reports it as a bug. If true per-user persistence is a requirement, you need a server-side preference store — that's a fork, not a config toggle.
The one shipped bug is the template for the next one. v1.0.0's grip blocked the sidebar scrollbar; v1.0.1 moved it to a "central resize grip." That class of failure — an absolutely positioned overlay intercepting pointer events over the navigation — is exactly what recurs when Filament changes its sidebar DOM. Always test with enough nav items to make the sidebar scroll on a short viewport (or a zoomed-in browser at 150%). That's where this package broke last time and where it will break again. If the sidebar can't be scrolled, navigation is unusable and every admin user is affected at once.
Expect a flash of default width. Reading localStorage and applying it happens after first paint. On every navigation you may see the sidebar render at the default width for a frame, then snap to the saved one. It's cosmetic, but on a slow connection or a large panel it's visible. Mitigation is an inline <head> script that applies the stored width before paint — which means forking the package's init. Decide if it's worth it; for most internal panels it isn't.
Config caching will bite you on the first config change. Publish the config, set your min/max, then remember that production runs config:cache. If you edit the config file on a server without re-caching (or if you publish it after caching), your bounds silently don't apply and the package falls back to its defaults. Add the config publish step to your deploy ordering: publish → cache config → filament:assets.
Watch for an inverted min/max. If the config permits max < min with no validation, the drag behaviour becomes undefined — the grip may stick, jump, or pin to the boundary. Set both explicitly and sanity-check them; don't rely on defaults you haven't read.
Mobile drawer is a separate surface. The sidebar becomes an off-canvas drawer below Filament's mobile breakpoint. A fixed pixel width plus a drag grip in that context is at best pointless and at worst a horizontal overflow bug. Test at ~375px width. If it's broken, the cheap fix is a CSS media query that hides the grip and forces width: 100% in the drawer — but again, that's your override, not a config option.
Accessibility is pointer-only unless proven otherwise. A drag handle typically ships with no role="separator", no aria-valuenow, no tabindex, and no arrow-key handling. If your organization has a keyboard-accessibility standard, this package does not meet it out of the box and you should budget for adding keyboard equivalents (left/right arrows adjusting width, Home to reset) rather than assuming it's fine because "it's just a resize handle." Verify before rollout, not after.
Debugging: three places to look. (1) DevTools → Application → Local Storage for the package's key — is it being written at all? (2) Console for JS errors on livewire:navigated — the grip often works on first load and dies on SPA navigation. (3) The DOM inspector on .fi-sidebar — is the inline width being applied and then overridden by your theme? Ninety percent of reported bugs resolve in one of those three.
The exit cost is an afternoon, so don't over-invest. Seven stars, zero dependents, one maintainer, one drive-by contributor. The code surface is a grip, a drag handler, and a localStorage read/write. If upstream stalls on a Filament major, port the CSS/JS into your own panel theme and drop the dependency. That bounded exit is the only reason this is a reasonable adoption — treat "we will fork it in an afternoon if needed" as the plan, not the contingency, and note the pinned commit SHA in your upgrade runbook.
Pin the version. Use an exact constraint (1.0.1), not ^1.0. A micro-dependency this small gives you no signal on what changed between patches, and the failure mode is visual — a silent cosmetic regression that no test will catch.
How can I help you explore Laravel packages today?