Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Collapsible Subnav Laravel Package

emuniq/filament-collapsible-subnav

A Filament v3, v4, and v5 plugin that adds a collapsible toggle to sub-navigation sidebars on resource pages. It auto-registers to all panels with zero configuration and works with both top and sidebar navigation layouts.

View on GitHub
Deep Wiki
Context7

Getting Started

Install is genuinely one command. No config publish, no service provider edit, no panel wiring required.

composer require emuniq/filament-collapsible-subnav
php artisan optimize:clear

The plugin auto-registers against every panel in the application. Confirm it booted by viewing source on a Filament page and looking for the inline critical CSS/script block in <head>. That block is the FOUC-prevention mechanism — if it's absent, nothing else will work.

The one prerequisite that gates everything: the page must render a sub-navigation sidebar. That means a Resource or Page whose sub-nav position is Start, not End or Top.

// Filament v3
protected static SubNavigationPosition $subNavigationPosition = SubNavigationPosition::Start;

// Filament v4 / v5
public static function getSubNavigationPosition(): SubNavigationPosition
{
    return SubNavigationPosition::Start;
}

If the toggle is missing, check this before anything else. The plugin deliberately does not touch the main panel sidebar — it only targets the secondary nav column inside resource pages.

First use case to validate: a resource detail page with enough tabs that the sub-nav column is eating content width — realistically 6+ tabs on a 1280–1440px viewport. Open it, click the toggle, confirm the subnav_collapsed cookie appears in DevTools, then hard-reload and verify there is no flash of the expanded state. That flash test is the entire reason to take a dependency here rather than writing twenty lines of CSS yourself — validate it in your real stack (behind your CDN, with your minifier), not on php artisan serve.

Where to look in vendor code first: the inline <head> injection and the livewire:navigated listener. Those two files are the only non-obvious logic in the package; everything else is CSS selectors. Read them both before you decide whether fork risk is acceptable.

Implementation Patterns

Register explicitly, even though you don't have to

Auto-registration means composer require silently changes every panel in the app. On a shared codebase, make it a reviewable diff instead:

use Emuniq\FilamentCollapsibleSubnav\CollapsibleSubnavPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(CollapsibleSubnavPlugin::make());
}

The explicit call is a no-op if auto-registration already fired, so there's no double-render cost — but the diff makes the blast radius visible to reviewers.

Use SubNavigationPosition::Start as your feature flag

You don't need a config toggle. Flip sub-nav position per resource: pages with Start get the collapsible sidebar, everything else is untouched. That gives you granular rollout with zero extra code, and reframes the team conversation from "should we install this plugin" to "which resource pages should have a Start sub-nav" — a much easier question to answer per-page.

SPA mode is the strongest technical case

If your panel uses ->spa(), hand-rolled collapse code bound to DOMContentLoaded will desync after the first Livewire navigation: the class persists on stale nodes or vanishes entirely. The plugin re-applies collapsed state and tooltips on livewire:navigated:

public function panel(Panel $panel): Panel
{
    return $panel
        ->spa()
        ->plugin(CollapsibleSubnavPlugin::make());
}

If you vendor or fork the package, preserve that listener — it's the majority of the non-trivial logic.

Optional theme integration

php artisan collapsible-subnav:install
npm run build

This folds the plugin CSS into your compiled theme and removes one inline block per response. Worth doing if you're strict about response size or run a CSP that dislikes inline styles. Skip it if you have a custom theme you don't want to rebuild — the plugin works identically without it.

Pin the version and name an owner

"emuniq/filament-collapsible-subnav": "^1.6"

Single maintainer, ~10 stars, zero dependents. The realistic failure mode isn't a security incident — it's a silent visual regression after a Filament minor bump that a user notices first. Pin, and decide internally who watches for it.

Ship one smoke test

Whatever your browser-test stack is (Dusk, Pest browser, Playwright), assert three things on one sub-nav page: the toggle exists, clicking it applies the collapsed class, and a reload keeps it collapsed. That single check is what stands between you and the quiet-regression failure mode described above.

Treat it as a diagnostic, not just a UX tweak

Roll it out to one page, measure the baseline (tab click-through, or time-to-complete for that page's primary task), and re-measure after two weeks. If nobody ever expands the sidebar again, the useful finding isn't "nice toggle" — it's "this page has too many tabs and should be split."

Gotchas and Tips

Selector brittleness across Filament majors is the real maintenance cost. Filament v4 renamed .fi-sidebar-item-button to .fi-sidebar-item-btn, which silently killed tooltips until v1.6.0 — no error, no warning, just missing hover text. Assume the next major does the same. When you bump Filament, manually check four things on a collapsed sub-nav: tooltip on hover, hidden badges (.fi-sidebar-item-badge-ctn), correct button padding/centering, and aria-label presence. Budget this as recurring maintenance.

Tooltips differ by Filament version. v3 uses Tippy; v4 doesn't expose Tippy globally, so the plugin falls back to a CSS ::after tooltip plus the native title attribute. If you've themed tooltips elsewhere in your panel, the collapsed state may look subtly inconsistent on v4/v5. Check visually rather than assuming parity.

Cloudflare Rocket Loader can strip the early script and reintroduce FOUC. The plugin tags its inline script with data-cfasync="false" to survive Rocket Loader. If you still see a flash on reload in production, inspect the served HTML and confirm that attribute survived — HTML minifiers and some edge workers drop unknown attributes. Always test behind your actual CDN.

The cookie is domain-wide and single-named. subnav_collapsed is one value shared across every panel and every resource with a Start sub-nav. A user who collapses on Panel A gets collapsed state on Panel B, and a user who collapses one resource collapses all of them. Usually fine — occasionally surprising during a staged rollout. Clear the cookie if you're demoing expanded state.

No config file means no knobs. There's no published config, no width token, no callback hook. Customisation paths are limited to (a) CSS overrides in your own theme targeting the plugin's selectors, or (b) forking. Decide which you're willing to own before you need it, not after.

Collapsed mode is hidden below 768px. On mobile the toggle and collapsed state are moot — sub-nav is already handled responsively by Filament. Don't file a bug when you can't reproduce on a phone.

Dark mode follows Filament's dark class, not prefers-color-scheme. If your panel toggles theme via a custom mechanism, verify tooltip and border styling in both modes on v4/v5 specifically.

Debugging checklist, in order: (1) is sub-nav position Start? (2) is the <head> inline block present in view-source? (3) does the subnav_collapsed cookie get set on click? (4) if SPA mode, does the class survive navigation? (5) does the inline script still carry data-cfasync="false" in production HTML? Each step isolates a different layer — server registration, head injection, JS handler, navigation lifecycle, CDN — and the answers narrow the problem fast.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package