Filament Navigation Footermenu
Configurable footer navigation for Filament v4, v5: collapsible sidebar group and topbar dropdown (dark mode ready).
#Filament Navigation Footer Menu
A Filament v4, v5 panel plugin that adds a configurable footer navigation block to your panel:
- Sidebar mode (default navigation): a collapsible group at the bottom of the sidebar, aligned with Filament’s native navigation styling. Items expand upward so the trigger stays at the bottom (useful above the user area).
- Top navigation mode (
$panel->topNavigation()): a compact icon trigger with a dropdown menu, placed in the top bar with correct spacing next to the user menu.
Styling uses Filament’s own components and CSS tokens, so light/dark mode matches the rest of your panel.
#Requirements
| Requirement | Version |
|---|---|
| PHP | ^8.2 |
| Laravel (illuminate components) | ^11.0 | ^12.0 | ^13.0 |
| Filament | ^4.0 | ^5.0 |
#Installation
#1. Install the package
From Packagist:
composer require cyberline/filament-navigation-footermenu
From a GitHub/VCS repository (before Packagist, or for forks):
{ "repositories": [ { "type": "vcs", "url": "https://github.com/CyberLine/filament-navigation-footermenu.git" } ], "require": { "cyberline/filament-navigation-footermenu": "^1.0" } }
Local path repository (monorepo or development):
{ "repositories": [ { "type": "path", "url": "packages/filament-navigation-footermenu", "options": { "symlink": true } } ], "require": { "cyberline/filament-navigation-footermenu": "^1.0" } }
Stable installs: this package declares a concrete
versionincomposer.jsonso projects with"minimum-stability": "stable"can require it without treating the VCS checkout asdev-main.
#2. Register the Laravel service provider
The package registers FooterMenuServiceProvider via Composer’s extra.laravel.providers for package discovery.
In fresh clones or CI, if bootstrap/cache/packages.php is missing or package:discover did not run, you may see:
No hint path defined for [filament-navigation-footermenu].
Alternatively, ensure composer install / php artisan package:discover completes successfully after every deploy.
#3. Register the Filament plugin on your panel
In your PanelProvider (e.g. app/Providers/Filament/AdminPanelProvider.php), add the plugin to the panel’s plugins array:
use Cyberline\FilamentNavigationFootermenu\Data\FooterMenuItem; use Cyberline\FilamentNavigationFootermenu\FooterMenuPlugin; public function panel(Panel $panel): Panel { return $panel // ... ->plugins([ FooterMenuPlugin::make() ->triggerLabel('Legal') ->triggerIcon('heroicon-o-scale') ->items([ FooterMenuItem::make('Privacy policy') ->icon('heroicon-o-shield-check') ->url(fn () => route('legal.privacy')) ->openUrlInNewTab(), ]), ]); }
No ->register() call on the plugin is required beyond Filament’s normal plugin registration on the panel.
#Publishing (optional)
Publish and customize config, views, or translations:
php artisan vendor:publish --tag=filament-navigation-footermenu-config php artisan vendor:publish --tag=filament-navigation-footermenu-views php artisan vendor:publish --tag=filament-navigation-footermenu-lang
After publishing views, your copies live under resources/views/vendor/filament-navigation-footermenu/.
#Configuration
Default values are merged from config/filament-navigation-footermenu.php.
| Key | Purpose |
|---|---|
trigger.label |
Default trigger label if you do not call ->triggerLabel() on the plugin. |
trigger.icon |
Default Heroicon name for the trigger when you do not call ->triggerIcon(). |
heading |
Optional heading shown above the topbar dropdown list (sidebar group does not use it for the default list UI). |
items |
Array of item definitions (see Array-based items). Used when you do not call ->items() on the plugin. |
You can leave everything in config, override everything in the panel, or mix (plugin fluent API wins over config for the options you set).
#Usage
#Fluent API (FooterMenuPlugin)
All chainable methods return static for fluent configuration.
| Method | Description |
|---|---|
triggerLabel(string|Closure|null $label) |
Label for the sidebar group / accessible name for the topbar icon. |
triggerIcon(string|Closure|null $icon) |
Heroicon (or Filament-supported icon) for the trigger. |
heading(string|Closure|null $heading) |
Optional heading in the topbar dropdown. |
items(array|Closure $items) |
Menu entries: FooterMenuItem instances and/or arrays (see below). |
view(?string $bladeView) |
Custom Blade view for item content (sidebar list and/or dropdown body). |
visible(bool|Closure $condition) |
Hide the entire footer menu when false. |
sort(int $sort) |
Reserved for ordering relative to other plugins (Filament plugin sort). |
extraAttributes(array|Closure $attributes) |
Extra HTML attributes merged onto the root wrapper (e.g. class for a top border). |
Example – separator from main nav (Tailwind classes):
FooterMenuPlugin::make() ->extraAttributes([ 'class' => 'border-t border-gray-200 pt-3 dark:border-white/10', ]) ->triggerLabel('Legal') ->items([ /* ... */ ]);
#Fluent item API (FooterMenuItem)
FooterMenuItem::make(string $label) ->icon(?string $icon) // Heroicon name, etc. ->url(string|Closure|null $url) // Resolved to string for links ->openUrlInNewTab(bool|Closure $open = true) ->visible(bool|Closure $visible) ->badge(string|int|Closure|null $badge, string|Closure|null $color = null) ->badgeTooltip(string|Closure|null $tooltip)
Resolved row shape (useful inside custom Blade): label, icon, url, open_in_new_tab, badge, badge_color, badge_tooltip.
#Array-based items
Arrays are normalized to FooterMenuItem internally. Supported keys:
| Key | Aliases | Notes |
|---|---|---|
label |
— | Required, string. |
icon |
— | Optional string or Closure. |
url |
— | String, Closure, or null (# when null). |
open_in_new_tab |
openUrlInNewTab, new_tab |
Boolean or Closure. |
visible |
— | Boolean or Closure. |
badge |
— | String, int, Closure, or null. |
badge_color |
badgeColor |
Optional string or Closure. |
badge_tooltip |
badgeTooltip |
Optional string or Closure. |
Example:
FooterMenuPlugin::make()->items([ [ 'label' => 'Imprint', 'icon' => 'heroicon-o-identification', 'url' => fn () => route('legal.imprint'), 'new_tab' => true, 'badge' => '!', 'badge_color' => 'danger', 'badge_tooltip' => 'Action required', ], ]);
#Dynamic items with Closure
FooterMenuPlugin::make()->items(fn () => [ FooterMenuItem::make('Dashboard') ->url(fn () => url('/')) ->visible(fn () => auth()->user()?->isAdmin() ?? false), ]);
#Custom Blade view
Point the plugin at your own view:
FooterMenuPlugin::make() ->view('components.my-footer-menu');
Your view is included with the following variables (non-exhaustive):
| Variable | Description |
|---|---|
$plugin |
The FooterMenuPlugin instance. |
$layout |
'sidebar' or 'topbar'. |
$heading |
Resolved heading string or null. |
$triggerLabel |
Resolved trigger label. |
$triggerIcon |
Resolved trigger icon or null. |
$items |
Array of resolved item rows (see shape above). |
$topbarAfterUserMenu |
bool – true when the topbar UI is rendered after the user menu (inside .fi-topbar-end). Useful if your custom markup needs different spacing. |
When a custom view is set, the plugin still renders the outer shell (sidebar group / dropdown); your view replaces the default list of links only.
#Behaviour & layout
#Sidebar (default navigation)
- Registered on
PanelsRenderHook::SIDEBAR_FOOTER. - Renders below other sidebar footer content (e.g. user menu when shown in the sidebar), matching Filament’s footer hook order.
- Uses Filament sidebar group / item classes so spacing matches the main navigation.
#Top navigation
- When the panel uses top navigation, the plugin does not render in the sidebar footer hook for that panel state.
- Primary placement:
PanelsRenderHook::USER_MENU_AFTER— output sits inside.fi-topbar-end, so Filament’sgap-x-4applies between the user menu and your trigger (no overlap with the avatar). - Fallback: if there is no user menu in the topbar (
userMenu(false)or user menu only in the sidebar), the plugin renders onPanelsRenderHook::TOPBAR_ENDinstead, with extra margin so the trigger does not collide with adjacent controls.
The topbar trigger is an x-filament::icon-button with a circular hit area and hover styles consistent with Filament.
#Visibility and tenancy
The plugin does not render when:
- the user is not authenticated in the current panel context, or
- the panel has tenancy enabled and no tenant is resolved yet, or
->visible(false)(or aClosureresolving tofalse) is set on the plugin.
Use ->visible() for feature flags, permissions, or environment-specific menus.
#Translations
The package ships with English and German language files under the filament-navigation-footermenu translation namespace.
Example:
__('filament-navigation-footermenu::footermenu.default_trigger_label');
Publish if you need to override strings per app.
#Tailwind / Vite (Filament theme)
This package’s Blade views use Tailwind utility classes (for example px-6, pb-3, flex) alongside Filament’s fi-* classes. Filament’s default pre-built panel CSS is compiled from Filament’s own sources only; it does not scan vendor/cyberline/filament-navigation-footermenu, so those utilities may be missing in the browser unless your app compiles a custom Filament theme that includes this package in Tailwind’s content scan.
#Required steps (Filament v4+ with Vite)
-
Create a panel theme CSS file (e.g.
resources/css/filament/{panel-id}/theme.css). The Filament stub pattern is:@import '../../../../vendor/filament/filament/resources/css/theme.css'; @source '../../../../app/Filament/**/*'; @source '../../../../resources/views/filament/**/*'; @source '../../../../vendor/cyberline/filament-navigation-footermenu/resources/views/**/*.blade.php';
Adjust relative paths if your file lives elsewhere.
-
Register the theme on your panel in
PanelProvider:return $panel ->viteTheme('resources/css/filament/admin/theme.css'); // path to your theme.css
-
Add the theme to Vite in
vite.config.js(Laravel Viteinputarray) so it is built withnpm run build/npm run dev. -
Rebuild assets after upgrading this package, editing its views, or changing Tailwind classes in the theme (
npm run build, or keepnpm run devrunning).
#If you publish views
After php artisan vendor:publish --tag=filament-navigation-footermenu-views, add an @source line for your app copy so Tailwind scans the published blades, for example:
@source '../../../../resources/views/vendor/filament-navigation-footermenu/**/*.blade.php';
You can keep or remove the vendor @source depending on whether you still load views from the package.
#Optional: avoid a custom theme
You can avoid relying on extra Tailwind utilities by using only Filament’s documented fi-* patterns and inline styles the default bundle already includes, or by shipping a tiny non-Tailwind CSS file — but the default package views expect a theme build that scans them as above.
#License
MIT — see LICENSE.md.