Filament Widgets: Grid Layout, Dashboard & Responsive Design
yebor974

yebor974 @yebor974

About: Freelance - French IT Engineer passionate about Laravel and Filament PHP, creating innovative solutions to simplify web development. Founder of Filament Mastery.

Location:
Reunion Island, France
Joined:
May 5, 2025

Filament Widgets: Grid Layout, Dashboard & Responsive Design

Publish Date: May 12
12 9

Customizing the Filament Admin Panel Dashboard

Filament provides a powerful and flexible dashboard system, allowing developers to tailor the admin panel to their needs. In this guide, we’ll explore how to define a custom dashboard by leveraging inheritance, responsive column layouts, and dynamic widgets.

Creating a custom dashboard

To override the default Filament dashboard, first create a new class extending Filament\Pages\Dashboard. This class should be placed in the Pages directory of the panel, which by default is located at app/Filament/Pages/.

If you have multiple panels, ensure the custom dashboard is placed within the correct panel directory.

namespace App\Filament\Pages;

use Filament\Pages\Dashboard as DefaultDashboard;

class Dashboard extends DefaultDashboard
{ }
Enter fullscreen mode Exit fullscreen mode

Registering the custom dashboard in the panel provider

To use your custom dashboard, you need to remove the default declaration in the panel provider by removing it in the pages call:

namespace App\Providers\Filament;

use Filament\Facades\Filament;
use Filament\PanelProviders\PanelProvider;
use App\Filament\Pages\CustomDashboard;

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            //...
            ->pages([])
            //...;
    }
}
Enter fullscreen mode Exit fullscreen mode

Defining the grid of your dashboard

To define the number of columns in your dashboard grid, override the getColumns method:

namespace App\Filament\Pages;

use Filament\Pages\Dashboard as DefaultDashboard;

class Dashboard extends DefaultDashboard
{
    public function getColumns(): int | string | array
    {
        return 3;
    }
}
Enter fullscreen mode Exit fullscreen mode

By default, the dashboard grid has 2 columns. It must be between 1 and 12.

If you want a responsive grid, define it with breakpoints like this:

namespace App\Filament\Pages;

use Filament\Pages\Dashboard as DefaultDashboard;

class Dashboard extends DefaultDashboard
{
    public function getColumns(): int | string | array
    {
        return [
            'md' => 4,
            'xl' => 6,
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

This method ensures a responsive grid layout where:

  • On medium screens (md), there will be 4 columns.
  • On extra-large screens (xl), there will be 6 columns.

Creating and registering a Widget

Filament widgets allow you to add interactive elements such as charts, tables, and statistics.

Creating a basic Widget

In this example, we will create a StatsOverview widget using the following command:

php artisan make:filament-widget StatsOverview --stats-overview
Enter fullscreen mode Exit fullscreen mode

This command generates the widget in app\Filament\Widgets:

namespace App\Filament\Widgets;

use Filament\Widgets\Widget;

class StatsOverview extends Widget
{
    protected function getStats(): array
    {
        //...
    }
}
Enter fullscreen mode Exit fullscreen mode

Defining the width of your Widget

The columnSpan property defines how many columns of the parent component (e.g., the dashboard) the widget uses.

For a Static Dashboard Grid

You can define the number of parent columns the widget spans:

protected int | string | array $columnSpan = 2;
Enter fullscreen mode Exit fullscreen mode

The value must be less than or equal to the number of columns in your dashboard grid.

For a Responsive Dashboard Grid

You can define the column span with breakpoints like this:

namespace App\Filament\Widgets;

use Filament\Widgets\Widget;

class StatsOverview extends Widget
{
    protected int | string | array $columnSpan = [
        'md' => 2,
        'xl' => 3,
    ];
}
Enter fullscreen mode Exit fullscreen mode

Here, the widget spans:

  • 2 columns on medium screens (md).
  • 3 columns on extra-large screens (xl).

Alternatively, if you want a full-width widget (occupying the entire width of the dashboard grid), declare this:

protected int | string | array $columnSpan = 'full';
Enter fullscreen mode Exit fullscreen mode

In a Stats widget, you can combine it with the getColumns() method to define how many columns the widget contains.

Registering the Widget in the dashboard

By default, Filament automatically loads widgets from a specified directory. You can configure this in the panel provider:

public function panel(Panel $panel): Panel
{
    return $panel
        //....
        ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
        //...;
}
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can manually register the widget with the widgets method in the panel provider:

use Filament\Widgets\StatsOverview;

public function panel(Panel $panel): Panel
{
    return $panel
        //....
        ->widgets([StatsOverview::class])
        //...;
}
Enter fullscreen mode Exit fullscreen mode

Or, you can manually register the widget in your custom Dashboard class:

namespace App\Filament\Pages;

use Filament\Pages\Dashboard as DefaultDashboard;
use Filament\Widgets\StatsOverview;

class Dashboard extends DefaultDashboard
{
    public function getWidgets(): array
    {
        return [
            StatsOverview::class,
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

⚠️ Warning: If you use this last method, automatic widget discovery will be disabled.

Examples with a Responsive Dashboard Grid and an xl breakpoint of 6

  • A Stats widget with an xl breakpoint of 4 and a Chart widget with an xl breakpoint of 3
#In stats widget
protected int | string | array $columnSpan = [
    'xl' => 4,
];

#In chart widget
protected int | string | array $columnSpan = [
    'xl' => 3,
];
Enter fullscreen mode Exit fullscreen mode

Filament widgets - Stats & chart layout example

  • A Stats widget with an xl breakpoint of 4 but a number of columns of 2 (declares with the getColumns() method in the widget):
protected int | string | array $columnSpan = [
    'xl' => 4,
];

protected function getColumns(): int
{
    return 2; 
}
Enter fullscreen mode Exit fullscreen mode

 Filament widget - Stats layout example

  • A Stats widget with an xl breakpoint of 5 and a Chart widget with a full-width layout
#In stats widget
protected int | string | array $columnSpan = [
    'xl' => 5,
];

#In chart widget
protected int | string | array $columnSpan = 'full'
Enter fullscreen mode Exit fullscreen mode

Laravel Filament widgets - Chart widget with a full-width

If you enjoyed this article, feel free to explore more tutorials and plugin insights on Filament Mastery.

You can also join the newsletter to get new articles straight to your inbox.

Thanks for reading!

Comments 9 total

  • Michael Liang
    Michael LiangMay 12, 2025

    Great post

    • yebor974
      yebor974May 12, 2025

      @michael_liang_0208 Many thanks!

      • Michael Liang
        Michael LiangMay 12, 2025

        I use the react the most. So I know a little about Laravel.
        Could you tell me the advantages of Laravel?

        • yebor974
          yebor974May 12, 2025

          I’ve been using Laravel for over 12 years across different industries, and what I love the most is how quickly I can build and ship production-ready apps. It’s fast, secure, and comes with everything I need out of the box, from authentication to queues, scheduler, secure routing and more.
          The ecosystem keeps growing too, making it even easier to scale or add new features.
          And Filament is a game-changer for building beautiful admin panels in no time, perfect for managing data efficiently.
          If you’re coming from React, Laravel makes an excellent back-end for APIs, especially when paired with Sanctum or Passport for auth.
          One framework, everything you need in 99% of applications :)

  • Dotallio
    DotallioMay 12, 2025

    love these step-by-steps. always feels good when i can finally make my dashboard not look like default stuff lol

    • yebor974
      yebor974May 12, 2025

      Thanks @dotallio !
      I try to make articles clear and complete, not easy :)

  • Nevo David
    Nevo DavidMay 13, 2025

    this kinda control over dashboard layouts always gets me tweaking stuff for hours

    • yebor974
      yebor974May 13, 2025

      Yes, we quickly waste a lot of time 😄

Add comment