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

Nova Color Field Laravel Package

timothyasp/nova-color-field

A color picker field for Laravel Nova that adds an intuitive color selection input to your resource forms. Supports hex values and custom colors, integrates quickly into any Nova resource, and gives editors a clean, simple way to choose and store colors.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require timothyasp/nova-color-field

Before you wire it in, confirm two things:

  1. Nova version. The last release is July 2023, which lines up with Nova 4. There are zero dependents, so nobody else is field-testing Nova 5 compatibility for you. Check composer show laravel/nova timothyasp/nova-color-field and, if you're on Nova 5, smoke-test the form field in a branch before committing.
  2. The actual class/namespace. Open vendor/timothyasp/nova-color-field/src/ and confirm the namespace (commonly Timothyasp\Color\Color). The README snippet is the source of truth; a wrong use statement is the most common "it doesn't work" report.

Then it's a normal Nova field:

use Timothyasp\Color\Color;

public function fields(Request $request): array
{
    return [
        ID::make()->sortable(),
        Text::make('Name'),
        Color::make('Brand Color')
            ->rules('required', 'regex:/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/')
            ->help('Hex value, e.g. #FF5733'),
    ];
}

Migration — size the column for hex, not for a color name:

$table->string('brand_color', 9)->nullable(); // #RRGGBBAA fits; 7 if you only allow #RRGGBB

First use case: a Settings/SiteTheme resource (or a brand_color on Team/Product) where an admin picks a hex value and the front end consumes it via a CSS custom property. That exercises the whole path — form input, DB storage, index display, Blade output — in about 20 minutes.

Implementation Patterns

Treat it as a plain string field. The package stores a hex string; everything else is stock Nova. That means ->default('#0ea5e9'), ->nullable(), ->required(), ->help(), ->placeholder(), ->sortable(), ->onlyOnForms(), ->hideFromIndex() and ->rules() all behave exactly as they do on Text. Reach for those first before assuming the package needs to do more.

Normalize on the model, not in the field. Pickers can emit upper- or lower-case hex, or nothing at all. A mutator keeps the DB consistent and makes later where('brand_color', '#ff5733') queries sane:

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

Render a swatch where the field can't. If the field doesn't render a proper index/detail component to your taste, keep the value visible with a displayUsing on a Text field, or just use the color field for the form and a text/HTML field for the index:

Text::make('Brand Color', 'brand_color')
    ->displayUsing(fn ($value) => $value
        ? "<span style=\"display:inline-block;width:1rem;height:1rem;border-radius:3px;background:{$value}\"></span> {$value}"
        : '—')
    ->asHtml()
    ->onlyOnIndex(),

(Only do this because the hex is regex-validated — see the injection note below.)

Consume the value as a CSS variable rather than string-concatenating styles all over your views:

<div style="--brand: {{ $team->brand_color ?? '#0ea5e9' }}">…</div>
.btn-primary { background: var(--brand); }

Pairs well with: Image/File for logo + color, BelongsTo for per-tenant theming, and Flexible/Repeater (Nova 4) if you need a list of named swatches — the field itself is a standard form component and nests fine, but remember repeater contents serialize into a single JSON column, so you can't where() on them.

Defaults vs DB defaults. ->default() only pre-fills the create form. If records are also created outside Nova (seeders, imports, API), set a DB default or a model-level $attributes default too, or you'll have null colors in production while the form looked fine in staging.

Gotchas and Tips

  • Column width vs alpha. If you declare string('brand_color', 7) and a future picker setting emits #RRGGBBAA, MySQL strict mode errors or silently truncates depending on config. Use 9 and validate against the formats you actually accept.
  • Empty string vs null. Clearing a color picker can submit '' rather than null. With nullable plus a regex rule, '' fails validation while null passes. Either add 'sometimes'/Rule::requiredIf logic or coerce in the mutator (?string + ?: null), as above.
  • Field renders as a bare text input? The Vue asset didn't load. Confirm the package's service provider is registered (auto-discovery, or listed in config/app.php if discovery is disabled), then clear Nova's compiled assets (php artisan nova:publish, php artisan optimize:clear) and check the browser console for a missing field.js. Nova caches aggressively in production builds.
  • Dark mode. Third-party Vue color pickers frequently ship popovers with hard-coded light backgrounds and don't inherit Nova's dark theme. If the picker looks broken in dark mode, that's cosmetic and fixable by overriding styles in your own CSS — not a data problem.
  • The field writes to exactly one attribute. Don't point it at a JSON/settings column: the component receives the raw column value as a string, not a nested key. For multi-color settings, give each color its own column or write a small custom cast and a setter on the model.
  • Never interpolate the raw value into a style attribute without validation. asHtml() + style="background: {$value}" is a CSS/HTML injection vector if the column can be written outside Nova. Keep a regex rule on the field and normalize in the model; consider a sprintf with a whitelist when rendering.
  • Maintenance risk is the real story here. One maintainer, last release mid-2023, zero dependents. For a hex string in a form, that's acceptable — the PHP side is a few dozen lines. But budget for a fork: the extension point is trivial, subclass the field and override component(), or vendor the FormField.vue into resources/js/fields/ and register your own Nova::script(). Don't build your theming system around options this package might never gain.
  • Testing. There's no meaningful PHP logic to unit test — assert the round trip instead: $this->put(...) through a Nova action or assertDatabaseHas('teams', ['brand_color' => '#ff5733']), plus a validation test for a garbage value like red. That's where the actual bugs live (empty string, casing, column width).
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource