filamentphp make group of menu visible and invisible conditionally

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Conditionally Controlling Menu Visibility in FilamentPHP

As a senior developer working with Laravel and Filament, we frequently encounter scenarios where the user interface needs to adapt based on the current state of the application—whether that state is based on authentication status, user roles, or specific permissions. One common requirement is hiding entire menu groups when their contents are irrelevant to the logged-in user.

This post addresses a very specific challenge related to using packages like filament-authentication where you have predefined menu structures (like the 'authentication' group with 'Role', 'Permission', and 'User' menus) that should only appear if certain conditions are met.

The Challenge: Hiding Menu Groups Conditionally

When working with Filament, navigation is defined declaratively within the Panel configuration. If you simply want to hide a menu item, you use standard boolean checks. However, hiding an entire menu group requires controlling the parent element's visibility. The difficulty often lies in how packages define these groups internally, making direct visibility toggles on the group parent sometimes insufficient if the package enforces the structure rigidly.

The goal is to implement logic that evaluates a condition (e.g., "Is the user an admin?" or "Is this feature enabled?") and dynamically constructs the navigation bar accordingly.

The Solution: Dynamic Navigation Building

Since Filament relies heavily on Laravel's MVC structure, the most robust solution involves overriding or extending the method responsible for building your panel's navigation. Instead of relying solely on static definitions, we will build the menu array dynamically based on runtime conditions.

For this example, let’s assume you are customizing a Panel class where you define the navigation links. We can use Laravel’s conditional logic to determine which items get included in the final navigation structure.

Step-by-Step Implementation

We will modify the method that defines the navigation links within your Filament Panel class. This is where we inject our application logic before Filament renders the UI.

<?php

namespace App\Filament\Pages;

use Filament\Panel;
use Illuminate\Support\Facades\Auth;

class Dashboard extends Panel
{
    protected static ?string $navigationIcon = 'heroicon-o-dashboard';

    public function getNavigationItems(): array
    {
        $items = [];
        
        // 1. Check the condition: Only show authentication items if the user is logged in (or meets specific criteria)
        if (Auth::check()) {
            $items['authentication'] = [
                'label' => 'Authentication Settings',
                'icon' => 'heroicon-o-lock',
                // 2. Conditionally add sub-menus based on application context
                'Role' => [
                    'label' => 'User Roles',
                    'url' => route('filament.admin.pages.user-roles'), // Example route
                ],
                'Permission' => [
                    'label' => 'Permissions',
                    'url' => route('filament.admin.pages.permissions'),
                ],
                'User' => [
                    'label' => 'Manage Users',
                    'url' => route('filament.admin.pages.users'),
                ],
            ];
        } 
        // If the condition is false, we simply do not add the 'authentication' key to $items.

        return $items;
    }
}

Explanation and Best Practices

  1. Centralized Logic: By creating a dedicated method like getNavigationItems(), you separate the UI definition from the underlying data fetching logic. This aligns well with the principles of clean architecture found in modern Laravel applications, which emphasizes separating concerns—a core concept when building complex systems on top of Laravel framework components.
  2. Leveraging Auth State: We use Auth::check() to determine if the menu group is relevant. If this check fails, the entire 'authentication' group is omitted from the final array returned to Filament, effectively hiding it from the navigation.
  3. Package Integration: While you are using a package like filament-authentication, this dynamic approach allows you to override or augment the default structure provided by the package. If the package provides its own methods for menu building, look for hooks within those methods to inject your conditional logic rather than completely overriding the entire build process.
  4. Laravel Context: This pattern heavily utilizes Laravel's foundation. Just as you manage database relationships using Eloquent models, you manage UI structure by managing arrays and applying conditional logic based on the state retrieved from your application context (like session data or model attributes).

Conclusion

Conditionally controlling menu visibility in Filament is achieved not by simple CSS toggles, but by controlling the data that Filament uses to render the navigation. By implementing custom methods that dynamically build the navigation array based on runtime conditions—using Laravel's powerful conditional logic—you gain complete control over your application’s interface. This approach ensures that your UI is always synchronized with the current state of your application, making your code cleaner, more maintainable, and highly dynamic. Remember, mastering these underlying principles is key to building robust applications on top of frameworks like Laravel and Filament, much like understanding how data flows through Eloquent models or services within the larger ecosystem of laravelcompany.com.