sphinx-code-studio/filament-mobile-navigation
A Filament package that brings mobile-friendly navigation to your admin panel, with responsive menus, slide-out drawers, and touch-optimized layouts for a smoother experience on phones and tablets.
What this is: a Filament panel plugin (not a standalone Laravel package) that renders a mobile-first navigation surface — bottom tab bar plus a "More" sheet — for Filament resources and pages. It is UI-only: it does not change routing, policies, or your resources' behaviour.
Prerequisites
Minimal steps
composer require the package (vendor/name per the README).php artisan vendor:publish --tag="filament-mobile-navigation-config".public function panel(Panel $panel): Panel
{
return $panel
->plugin(MobileNavigationPlugin::make());
}
php artisan filament:optimize-clear / optimize:clear) and open the panel on a narrow viewport.Treat the exact class/method names above as illustrative — confirm against the README before wiring it in. At v0.1.0 the public API is new and undecorated.
Where to look first
src/*Plugin.php) and any Concerns/ or Contracts/ directory: that is where "class-based mobile navigation" is defined, and it tells you whether items are declared via static properties, static methods, or an interface you implement on Resources/Pages.resources/views/ — the Blade used for the tab bar and More sheet; publishable views are your escape hatch for layout tweaks.First use case to ship: a 4-item bottom bar on one panel — Dashboard, your most-edited Resource, a second Resource, and More. Get that working before touching grouping, positions, or multi-panel.
Curate, don't auto-resolve. "Automatic Filament navigation resolution" is the headline convenience and the headline risk: it will happily surface every navigable Resource. The durable pattern is explicit opt-in on a small set of classes, with automatic resolution as a fallback:
// On the Resource class — shape per README
public static function getMobileNavigationItem(): ?MobileNavigationItem
{
return MobileNavigationItem::make('Orders')
->icon('heroicon-o-shopping-bag')
->badge(fn () => Order::awaitingFulfilment()->count());
}
Keep the bar to 3–5 destinations. Everything else belongs in the More menu, grouped (Sales, Catalogue, Settings) so the sheet stays scannable on a 375px screen.
One plugin instance per panel. With multi-panel support, register the plugin in each panel provider independently and give each its own item set. A customer-facing panel and an internal ops panel should not share a tab bar. If you have tenancy, verify the nav is tenant-scoped — the Resource classes are, but a hand-built item pointing at a fixed URL may not be.
Delegate visibility to Filament, not to the plugin. Authorization and visibility support means canViewAny(), canAccess(), and shouldRegisterNavigation() are respected. So:
shouldRegisterNavigation(false) (or the plugin's equivalent) to keep desktop-only, report-style Resources out of the bar while leaving them routable.Let colour and dark mode be automatic. "Automatic Filament panel colors" and dark mode support mean you should not hardcode hex values in custom items. Use the panel's semantic colour names so a tenant-branded or dark palette flows through. This is also your cheapest regression test: switch the panel to dark and to a non-default primary colour and confirm the bar follows.
Position is a product decision, not a preference. Configurable menu position is usually bottom vs top. Bottom matches native app expectations and pairs with safe-area support on notched devices; top competes with Filament's own topbar and header actions. Pick one per panel and document it — mixed positions across panels confuse the same user.
Workflow tips
npm run build / npm run dev for the panel theme) after publishing views, or you will debug a CSS change that never shipped.php artisan config:cache locally before calling it done; plugins that read config at boot behave differently under cached config.It is v0.1.0 — pin it. "vendor/name": "0.1.*" (or an exact tag). Pre-1.0 Filament plugins routinely rename config keys and static methods between patches. Assume the next minor may break your item definitions, and keep those definitions in as few files as possible so the upgrade is a single diff.
Filament 4 and 5 in one package means branching. Nav registration, asset registration, and Blade component APIs differ between majors. Symptoms show up as duplicated nav items, a bar that renders but is inert, or assets not loading. Read the CHANGELOG on every bump and smoke-test on the major you actually run.
Safe-area support needs your layout's cooperation. The CSS relies on env(safe-area-inset-*), which is zero unless the viewport meta includes viewport-fit=cover. If you have a custom panel layout or a Blade wrapper that overrides the meta tag, the bar will sit under the iOS home indicator. Check the meta tag first when "the bar is cut off" is reported.
Livewire SPA navigation and active state. Filament navigates via wire:navigate. A tab bar built with plain anchors can lose its active highlight (or re-render oddly) after client-side navigation. If items look stale after a tap, that is the cause — prefer whatever helper the plugin exposes and verify by navigating back and forth without a hard reload.
Automatic resolution silently includes hidden-but-routable resources. Combined with authorization, this produces two different bugs: a tab that 403s (policy says no, nav says yes) and a tab that should exist but doesn't (resource is hidden from navigation, so mobile resolution skips it). When a tab is missing, check shouldRegisterNavigation before you check the plugin.
Don't debug the bar in isolation. Order of checks that actually resolves most reports: (1) php artisan config:clear / cache cleared, (2) the Resource is registered on this panel, (3) the user passes canViewAny, (4) the viewport is genuinely narrow (the plugin may only render below a breakpoint), (5) assets rebuilt.
Extension points worth knowing. Published views and the config file are the supported surface; subclassing plugin internals is not, at 0.x. If you need a bespoke item (a link to a custom Livewire page, an action that opens a modal), the class-based item API is the intended route — keep it in a small service provider or a dedicated MobileNavigation registrar class rather than scattering it across Resources.
Testing. Assert the bar renders for a permitted user and not for a denied one, using Filament's panel test helpers plus assertSee on the item label. Add one test that a Resource with shouldRegisterNavigation(false) does not appear. That trio catches most regressions on upgrade.
When not to adopt yet. If your Filament version is pinned and stable, your panel is desktop-first, or you cannot absorb a breaking change mid-quarter, wait for 0.2/0.3. The feature set is coherent but broad for an initial release — safe-area, RTL, dark mode, multi-panel, and two Filament majors is a lot of surface area to stabilise at once.
How can I help you explore Laravel packages today?