Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Simple Color Picker Laravel Package

teguhpermadi/filament-simple-color-picker

A lightweight, easy-to-use color picker form field for Filament. Add simple color selection to your admin panels and resources with minimal setup, supporting hex values and a clean, native-feeling UI that fits seamlessly into any Filament form.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require teguhpermadi/filament-simple-color-picker

This is a Filament form-field package, so the only real prerequisite is a working Filament panel (v3-era installs; confirm the constraint in composer.json before you pull it into a v4 panel). The package pins itself at 0.1.x, so require it with a caret on the minor, not a floating constraint:

"teguhpermadi/filament-simple-color-picker": "^0.1.4"

Where to look first

  1. README.md — the public API is a single component class; the README is the only place the exact namespace and method chain are documented.
  2. src/ — you are looking for one Forms\Components\* class plus a service provider that registers Blade views and a JS/CSS asset. Read the component's setUp() to see which fluent methods actually exist before you assume a Filament-native API.
  3. resources/ — the Blade view wrapping the JS picker. This is where you find out whether the picker is Alpine-driven or a third-party JS library bundled by the plugin.

First use case

The canonical job is a hex color on a settings or branding model:

use Filament\Forms\Components\TextInput;
// use the package's component — check README for the exact FQCN
use Teguhpermadi\FilamentSimpleColorPicker\Forms\Components\SimpleColorPicker;

SimpleColorPicker::make('brand_color')
    ->label('Brand colour')
    ->required(),

with a matching migration:

$table->string('brand_color', 9)->nullable(); // 9 to leave room for #RRGGBBAA

Render it back to the user with a swatch rather than raw hex — a colour field nobody can see is a support ticket waiting to happen. Filament's built-in ColorColumn or a TextColumn with ->badge()->color(fn ($state) => $state) both work on the stored hex string.

Implementation Patterns

Normalise on the way in, not on the way out. Pickers are inconsistent about the leading # and casing. Settle the contract at the model layer so every consumer (Blade, exports, an API) sees the same shape:

protected function brandColor(): Attribute
{
    return Attribute::make(
        set: fn (?string $value) => $value
            ? '#'.strtolower(ltrim($value, '#'))
            : null,
    );
}

Live preview. The field's payoff is instant feedback. Pair it with ->live() and repaint a dependent component:

SimpleColorPicker::make('brand_color')
    ->live()
    ->afterStateUpdated(fn ($state, Set $set) => $set('preview_text_color', ...)),

Wrap the reactive section in Section::make()->id('preview') and return it from ->reactive(), otherwise the DOM you update is the wrong one inside modals.

Constrain the palette. If you are picking a colour to sit inside a fixed design system, free-form picking is a liability. Either restrict swatches (if the component exposes a presets/->colors() style method — check setUp()), or validate against an allow-list:

->rules(['regex:/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/'])

Reuse outside resources. The component is a standard Filament field, so it drops into action modals (Action::make()->form([...])), custom Livewire forms using InteractsWithForms, and relation managers unchanged. The one thing that does not travel is the plugin registration — if the service provider is panel-scoped via ->plugin(), a standalone Livewire component outside that panel will render an unstyled input.

Multi-panel / theming. Register the plugin or rely on auto-discovery consistently across panels. If you publish the views to tweak the swatch layout, publish them once at the app level and remember that published views stop receiving upstream fixes.

Gotchas and Tips

Filament already ships ColorPicker. This is the first question to answer before adopting the package: Filament's own field supports hex/rgb/hsl formats and is maintained in lockstep with the framework. The package's reason to exist is presumably a lighter or simpler UI (hence "simple"), so evaluate it on that basis — not as a general-purpose colour field. If you need format conversion, alpha channels, or an eyedropper, use the native component.

Colour storage width. string('color', 7) silently truncates #RRGGBBAA. Choose 7 or 9 deliberately and write the migration to match the format the picker actually emits — verify by dumping $state from afterStateUpdated on a first render rather than trusting the README.

Asset publishing and caching. Filament plugin assets are registered through a manifest. After every composer update on this package, run the asset publish step (php artisan filament:assets, or vendor:publish --tag=filament-assets depending on how the provider registers) and clear php artisan optimize:clear. A stale manifest after a version bump is the single most common cause of "the field renders as a plain text input."

Repeaters and modals. Third-party JS pickers that attach on DOMContentLoaded break when a repeater row is added or a modal reopens. If the field goes dead on the second row, the fix is in the Blade view: hook into Livewire's lifecycle or Alpine's x-init on the element rather than a document-level listener. Report it upstream, but keep a local override ready.

Dark mode contrast. A swatch rendered with the raw hex next to dark panel chrome can disappear. Always give the swatch a border or ring. This is a rendering concern in your column/Blade, not the package's.

0.1.4 is an opaque patch. The release carries no changelog detail beyond a compare link, and the 0.1.x line makes no semver guarantees. Treat every bump as potentially breaking: pin the exact version in composer.json, read the diff (0.1.3...0.1.4) before deploying, and cover the field with a cheap smoke test so a silent API rename fails CI rather than production:

livewire(CreateBrand::class)
    ->fillForm(['brand_color' => '#ff0000'])
    ->call('create')
    ->assertHasNoFormErrors();

$this->assertDatabaseHas('brands', ['brand_color' => '#ff0000']);

Validation is on you. Do not assume the picker prevents free text. Users paste, autofill, and devtools exist — always attach a format rule server-side.

Extension point. The component's fluent API is thin; the realistic customisation path is publishing and overriding the Blade view. Fork the view into resources/views/vendor/... rather than editing vendor/, so the next patch does not silently revert your work.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource