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

Nova Detached Filters Laravel Package

outl1ne/nova-detached-filters

Nova Detached Filters lets you pull Laravel Nova filters out of the default filter dropdown and render them detached elsewhere on the page, keeping frequently used filters visible and one click away for faster resource browsing.

View on GitHub
Deep Wiki
Context7

Getting Started

Three steps, roughly ten minutes.

  1. Install and pin.

    composer require outl1ne/nova-detached-filters
    

    The service provider is auto-discovered — no config/app.php edit. Immediately pin the resolved constraint in composer.json ("outl1ne/nova-detached-filters": "3.0.1") rather than leaving a floating ^3.0, and make sure your laravel/nova constraint is explicit too. This package patches Nova's filter internals, not a stable public API.

  2. Read vendor/outl1ne/nova-detached-filters/src before you read anything else. It is a small package (a service provider, one or two PHP classes, one Vue component). The functional surface is one wrapper/flag plus a trait — five minutes in src/ tells you exactly which symbol marks a filter as detached, and that is faster and more reliable than skimming a README for a package this small. Confirm the class name before copy-pasting any snippet, including the ones below.

  3. Wire it into one resource. In app/Nova/User.php, wrap the filter you want promoted and leave the rest untouched:

    use Outl1ne\NovaDetachedFilters\...; // whatever `src/` shows
    
    public function filters(NovaRequest $request)
    {
        return [
            DetachedFilter::make(new UserStatus),  // rendered as a panel on the index
            new UserRole,                          // stays in the dropdown
        ];
    }
    

    Load the resource index. The status filter should now render as an always-visible panel above the table, behave identically to its dropdown version, and write the same ?user_status=... query string.

First use case: take your highest-traffic internal resource (tickets, orders, users) and promote exactly one filter — status or owner. Not three. Ship it, watch it for a week, then decide about a second.

Implementation Patterns

Mixed mode is the default, not a fallback. Detaching is per-filter-instance, so promoting one filter does not touch the others. Keep the long tail — rare date ranges, geo filters, admin-only flags — in the dropdown. A useful convention is "detached = a filter an operator touches on most visits; dropdown = a filter used weekly or less." Document that rule in one line in the resource class.

Adopt incrementally, one resource at a time. Never roll it across every resource in a single PR. Pick the resource where operators already complain about clicking, promote 1–2 filters, and let it sit. Expand only on an articulated win. This keeps the blast radius to a single file per resource and makes rollback a one-line delete.

Reuse the filter class; don't fork it. A detached filter is the same Filter subclass executing the same apply() — same query, same ->withMeta(), same defaults. If you find yourself writing a second "detached version" of a filter, you've misread the package. The only thing that changes is where the component mounts.

Order matters and follows filters(). Detached panels render in declaration order. Put the most-used filter leftmost/first; on narrower viewports the ordering is what protects the useful controls from being pushed off.

Custom filter components: verify visually first. Built-in Nova filters (BooleanFilter, SelectFilter, DateFilter, RangeFilter) render fine. Custom Vue filter components are the one place to check by hand — mount the component, apply a value, confirm the panel collapses/expands and the applied indicator is readable at panel width rather than dropdown width. If a custom component assumes a narrow container, that is your breakage, not the package's.

Treat the URL as the contract. Nova serializes filter state into the query string; detached filters participate in that unchanged. Your integration test is manual but quick: apply a detached filter → paginate → sort → copy the URL into a fresh tab → hit "reset filters." All four must show consistent state. Anything else generates "the numbers look wrong" tickets.

Codify a one-page convention alongside the first adoption: which filters are detached per resource, the rationale, and a query-cost check (does the filter's apply() do anything pathological on a large table?). Add "re-verify detached filters" to the Nova upgrade runbook the same day.

Gotchas and Tips

  • Nova-major coupling is the real risk. Patch 3.0.1 exists solely because Nova 5 changed types. Every Nova bump is a re-verification task. Pin the package version and an explicit Nova constraint together so an incidental composer update cannot silently orphan it.
  • Stale published assets break it first and most confusingly. After install or upgrade, confirm whether assets need php artisan nova:publish / vendor:publish, and that your deploy script runs the same. A half-published state shows as a blank index or a Vue console error that looks like the package is broken when it's actually a caching problem.
  • Toolbar collisions. Anything else touching Nova's index toolbar or filter menu (page managers, theme packs, other filter plugins) can produce duplicated or missing controls at runtime only. Test with your full dependency set installed, not in a scratch Nova.
  • Always-visible filters invite always-on filters. Operators will leave a detached date-range filter set to "all time" and it will fire on every index load. Enforce a query-cost review for anything you promote, and cap detached filters at 2–3 per resource — both for query cost and because horizontal space runs out before your filter list does.
  • Responsive layout degrades silently. Check a ~1280px viewport. Detached panels stack or compress, and filter state can become invisible while still applied — the worst combination (filtered data, no visible indication why).
  • It relocates filters; it does not extend them. No saved filter sets, no shareable named views, no cross-filter logic beyond what your Filter classes already do. If the ask is "save this filtered view," this package is not the answer and you should say so early.
  • Debugging technique: if a detached filter misbehaves, temporarily unwrap it back into the dropdown. If it works there, the problem is presentation/mounting; if it fails there too, it was never the package. This one move cuts triage time in half.
  • Forking is a realistic fallback, not a last resort. Single maintainer, ~63 stars, zero listed dependents: assume you are near the front of the issue queue. The code footprint is small enough that vendoring it internally is an afternoon, so treat "pin + fork plan" as the standard posture rather than an escalation.
  • Scope check: it is inert outside Laravel Nova. Don't evaluate it for a Filament or custom admin migration; and keep it out of customer-facing surfaces — always-visible filters are an internal-ergonomics pattern.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console