Building a custom color palette field in Filament - Part 0

laravel
Table of Contents

In this short series of blog posts, I'll show you how to create a custom Filament field.

The field we'll be building is a color palette field that lets you select a color from a fixed list of options. Such a simple field will cover the basics of rendering a field and syncing the selected option with the property on the form itself.

Here's an example of the field's API:

ColorPalette::make('color')
    ->options([
        '#ffffff' => 'White',
        '#000000' => 'Black',
    ]),

The color options will be an array of colors and labels. The label will be used to show a tooltip when hovering over the chosen color and the color value itself will be used to render the option.

To generate an empty field, run the php artisan make:form-field command.

$ php artisan make:form-field

Name (e.g. `RangeSlider`):
> ColorPalette

Successfully created ColorPalette!

This command is provided by the filament/forms package and will generate a basic Field class and corresponding Blade view.

Open up the new app/Forms/Components/ColorPalette.php file and you should see this:

<?php

namespace App\Forms\Components;

use Filament\Forms\Components\Field;

class ColorPalette extends Field
{
    protected string $view = 'forms.components.color-palette';
}

The field is already setup to render a particular Blade view, so let's also take a look at that.

<x-forms::field-wrapper
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <div x-data="{ state: $wire.entangle('{{ $getStatePath() }}') }">
        <!-- Interact with the `state` property in Alpine.js -->
    </div>
</x-forms::field-wrapper>

The boilerplate code inside of the Blade view might be a bit overwhelming at first, but it's actually Filament doing a lot of the heavy lifting for us. It's configuring the field wrapper (the component that renders the label, helper text, etc) and also gives us a basic Alpine component with the field's property already "entangled".

If we render this almost empty field inside of a form, you'll see something like this.

In the next part, we'll add a method to the field that accepts an array of options and start rendering some option buttons to the front-end.

Enjoyed this post or found it useful? Please consider sharing it on Twitter.