DEV Community

Fazail Alam
Fazail Alam

Posted on • Originally published at codef.site on

How to customize Laravel filament login page

"Laravel filament custom login page"

Laravel filament is a set of tools from which you can rapidly build stack application. Currently it has 3 tools, Admin Panel, Form Builder and Table Builder. There are also community plugin to support Laravel filament.

TALL stack

Tall stack is full stack framework for laravel. It stands for T: Tailwindcss , A: Alpinejs , L: Laravel and L: Livewire.

Getting Started

I assume that you have already installed Laravel and Filament. If not than check here for setting up filament. First publish configuration and views of filament.

php artisan vendor:publish --tag=filament-config
Enter fullscreen mode Exit fullscreen mode
php artisan vendor:publish --tag=filament-views
Enter fullscreen mode Exit fullscreen mode

Generated Files:

/
|-- config/
| |-- filament.php
|-- resources/
| |-- views/
| |-- vendor/
| |-- filament/
| ...
| |-- login.blade.php
Enter fullscreen mode Exit fullscreen mode

This will publish filament configuration and views.

Vite setup for filament

The current default bundler for laravel is vitejs, so if you have created a new project then there is greater chance that it came with vite. If it is then we have to register render hook head.end in register method of AppServiceProvider. We need to add @vite directive in order to use the compiled css and js files for our admin panel.

use Filament\Facades\Filament;

public function register()
{
    Filament::registerRenderHook(
        'head.end',
        fn (): string => Blade::render('@vite([\'resources/css/app.css\',\'resources/js/app.js\'])'),
    );
}
Enter fullscreen mode Exit fullscreen mode

For the icons i am using Iconify, so we need to register cdn script for iconify.

public function boot()
{
    Filament::registerScripts([
        'https://code.iconify.design/2/2.2.1/iconify.min.js',
    ], true); // true means that this script will be load before filament core scripts.
}
Enter fullscreen mode Exit fullscreen mode

We also need to use filament's tailwind configuration otherwise styling of the admin panel will not work. we can use tailwind's presets property to use preset configuration.

module.exports = {
    ...
    presets: [require("./vendor/filament/filament/tailwind.config.js")],
}
Enter fullscreen mode Exit fullscreen mode

Change login class

Since filament uses livewire component to render inputs of login form, we need to create our own class components. Copy the code of vendor/filament/filament/src/Http/Livewire/Auth/Login.php file then create a new file app/Filament/Auth/Login.php and paste the code in it. Next change the namespace of the class to namespace App\Filament\Auth;. Then pass the class into filament config file under auth.pages.login.

//app/Filament/Auth/Login.php
<?php

namespace App\Filament\Auth;

use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
use DanHarrin\LivewireRateLimiting\WithRateLimiting;
use Filament\Facades\Filament;
use Filament\Forms\ComponentContainer;
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Http\Responses\Auth\Contracts\LoginResponse;
use Illuminate\Contracts\View\View;
use Livewire\Component;

/**
 * @property ComponentContainer $form
 */
class Login extends Component implements HasForms
{
    use InteractsWithForms;
    use WithRateLimiting;

    public $email = '';
    public $password = '';
    public $remember = false;

    public function mount(): void
    {
        if (Filament::auth()->check()) {
            redirect()->intended(Filament::getUrl());
        }

        $this->form->fill();

    }

    public function authenticate(): ?LoginResponse
    {
        try {
            $this->rateLimit(5);
        } catch (TooManyRequestsException $exception) {
            $this->addError('email', __('filament::login.messages.throttled', [
                'seconds' => $exception->secondsUntilAvailable,
                'minutes' => ceil($exception->secondsUntilAvailable / 60),
            ]));

            return null;
        }

        $data = $this->form->getState();

        if (!Filament::auth()->attempt([
            'email' => $data['email'],
            'password' => $data['password'],
        ], $data['remember'])) {
            $this->addError('email', __('filament::login.messages.failed'));

            return null;
        }

        return app(LoginResponse::class);
    }

    protected function getFormSchema(): array
    {
        return [
            TextInput::make('email')
                ->label(__('filament::login.fields.email.label'))
                ->email()
                ->required()
                ->autocomplete(),
            TextInput::make('password')
                ->label(__('filament::login.fields.password.label'))
                ->password()
                ->required(),
            Checkbox::make('remember')
                ->label(__('filament::login.fields.remember.label')),
        ];
    }

    public function render(): View
    {
        return view('filament::login')
            ->layout('filament::components.layouts.card', [
                'title' => __('filament::login.title'),
            ]);
    }
}
Enter fullscreen mode Exit fullscreen mode
use App\Filament\Auth\Login;

return [
    ...
    'auth' =&gt; [
        'pages' =&gt; [
            'login' =&gt; Login::class,
        ],
    ],
];

Enter fullscreen mode Exit fullscreen mode

Login page

Now lets customize our blade file. This is default blade file for login page.

<form wire:submit.prevent="authenticate" class="space-y-8">
    {{ $this->form }}

    <x-filament::button type="submit" form="authenticate" class="w-full">
        {{ __('filament::login.buttons.submit.label') }}
    </x-filament::button>
</form>
Enter fullscreen mode Exit fullscreen mode

Login page before customization

We will add icons for social logins for example facebook, google, etc.

<form wire:submit.prevent="authenticate" class="space-y-8">
    {{ $this->form }}

    <x-filament::button type="submit" form="authenticate" class="w-full">
        {{ __('filament::login.buttons.submit.label') }}
    </x-filament::button>
    <div class="flex items-center space-x-4">
        <div class="border-t-2 border-slate-600 w-full h-1"></div>
        <h1>Or</h1>
        <div class="border-t-2 border-slate-600 w-full h-1"></div>
    </div>
    <div class="flex space-x-4 items-center justify-evenly">
        // icons from iconify
        <span class="iconify w-5 h-5" data-icon="flat-color-icons:google"></span>
        <span class="iconify w-5 h-5" data-icon="logos:github-icon"></span>
        <span class="iconify w-5 h-5" data-icon="logos:facebook"></span>
    </div>
</form>
Enter fullscreen mode Exit fullscreen mode

Login page after customization

Example

Lets make a simple example in which email and password will be auto filled when in local environment. This will help us quickly login in local environment. Open Login.php file and on mount method add the following code.

public function mount(): void
{
    if(env('APP_ENV') === 'local'){
        // fill method is from HasForms interface 
        $this-&gt;form-&gt;fill([
            'email'=&gt; 'fazailalam898@gmail.com',
            'password'=&gt; '12345678',
        ]);
    }else{
        $this-&gt;form-&gt;fill();
    }
}
Enter fullscreen mode Exit fullscreen mode

All right all done, now goto https://localhost:8000/admin/login and check for changes.

Top comments (1)

Collapse
 
qubadoff profile image
Siyasat Gubadov

Thanks