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

Color Picker Bundle Laravel Package

codeplace-io/color-picker-bundle

codeplace-io/color-picker-bundle adds a reusable color picker form field to Symfony applications. It offers configurable picker options, simple asset and Twig integration, and a straightforward way to add color selection to admin panels, settings pages, and other forms.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: it is a Symfony bundle, not a Laravel package. The repo is Wandi/ColorPickerBundle published as codeplace-io/color-picker-bundle, with zero stars and zero dependents. There is no service provider, no facade, no config publish tag, and no laravel/framework constraint anywhere. composer require will technically resolve (it pulls Symfony components), but nothing boots — Laravel's package discovery has nothing to discover.

So the "getting started" path for a Laravel dev is evaluation, then port, not installation.

Minimal steps, in order:

  1. composer show codeplace-io/color-picker-bundle --all (or clone the repo and read composer.json). You are looking for three things: the type (symfony-bundle), the PHP/Symfony version constraints under require, and extra.symfony. If it pins symfony/form: ^3.x|^4.x, it will conflict with the Symfony 6/7 components a modern Laravel app drags in transitively — that's a blocker, not a to-do.
  2. Find the bundle class (Wandi\ColorPickerBundle\WandiColorPickerBundle) and DependencyInjection/Configuration.php. The config tree is your only documentation for what options exist (theme, default format, picker library).
  3. Find the form type — almost certainly Form/Type/ColorPickerType.php. This class is the entire payload. Everything else is Symfony plumbing you will not reuse.
  4. Find the assets — Resources/public/js/* and Resources/public/css/*. This is the only part you can lift verbatim, and it's the only part worth lifting.

First use case: a brand-color field on a settings page. Do not install the bundle for this. Spend 30–60 minutes extracting the JS picker and reimplementing the field as a Blade component plus a validation rule. That is cheaper than one hour of Symfony-bundle archaeology, and you end up with code your team actually owns.

If you're on a mixed stack and genuinely need the Symfony Form type, that's a different document — this one assumes a Laravel app.

Implementation Patterns

1. Blade component wrapper. Mirror the Symfony type's options (format, value, theme) as props and keep the component dumb:

{{-- resources/views/components/color-picker.blade.php --}}
@props(['name', 'value' => '#000000', 'format' => 'hex'])

<div class="color-picker" data-colorpicker data-format="{{ $format }}">
    <input type="text"
           name="{{ $name }}"
           id="{{ $id = $attributes->get('id', $name) }}"
           value="{{ old($name, $value) }}"
           pattern="^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"
           {{ $attributes->except('id')->merge(['class' => 'color-picker__input']) }}>
</div>

2. Initialize once, in your Vite entry. Do not inline <script> tags per field. The bundle's Twig template attaches a data-* hook and a single init pass; replicate that in resources/js/app.js so it survives Turbo/Livewire navigation:

import Pickr from '@simonwep/pickr'; // or whatever the bundle actually wraps

const init = (root = document) => {
  root.querySelectorAll('[data-colorpicker]:not([data-ready])').forEach((el) => {
    el.dataset.ready = '1';
    const input = el.querySelector('input');
    Pickr.create({ el, default: input.value, components: { preview: true, opacity: false, hue: true } })
      .on('save', (color) => { input.value = color.toHEXA().toString(3).toUpperCase(); });
  });
};

document.addEventListener('DOMContentLoaded', () => init());
document.addEventListener('livewire:navigated', () => init());

3. Validation is a first-class concern, and the bundle won't give it to you. Symfony's default would be a Regex/Assert constraint; in Laravel make it a rule and reuse it everywhere:

class HexColor implements ValidationRule
{
    public function __construct(private bool $allowAlpha = false) {}

    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $pattern = $this->allowAlpha
            ? '/^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3,4})$/'
            : '/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/';

        if (!is_string($value) || !preg_match($pattern, $value)) {
            $fail('The :attribute must be a valid hex color.');
        }
    }
}

4. Normalize on the way in, not on the way out. Pickers emit #fff, #FFFFFF, and occasionally rgba(...). Store one canonical shape so your CSS and queries stay sane:

class HexColorCast implements CastsAttributes
{
    public function get($model, $key, $value, $attributes): ?string
    {
        return $value;
    }

    public function set($model, $key, $value, $attributes): array
    {
        return [$key => $value === null ? null : strtoupper(
            '#'.ltrim(preg_replace('/[^0-9A-Fa-f]/', '', $value), '#')
        )];
    }
}

Pair it with $table->char('brand_color', 7) (or 9 with alpha) and a factory default of '#000000'. Validate the length after normalization — #FFF expanding to #FFFFFF is a decision, not an accident.

5. Config over YAML. The bundle exposes picker options through config/packages/wandi_color_picker.yaml. Translate that into config/color-picker.php returning ['default_format' => 'hex', 'theme' => 'classic', 'allow_alpha' => false] and read it via config() in the component. Same extension point, Laravel-native.

6. Livewire. Wrap the widget in wire:ignore and re-init inside Livewire.hook('morph.updated'). Morphing the DOM under an initialized picker leaves a detached instance that still writes to a stale input — a classic silent data-loss bug.

7. Contributing back / debugging upstream. Clone, run its PHPUnit suite (expect KernelTestCase), and open the Twig template to see exactly which data-* attributes the JS binds to. Mirror those attribute names in the Blade component so the two stay behaviorally identical, then you can diff against the upstream asset when it changes.

Gotchas and Tips

  • Auto-discovery will not save you. No extra.laravel.providers exists. Even if a provider were added, the bundle's Extension and Configuration classes only run inside Symfony's kernel. Don't try to make them load — the payoff for a color input is nil.
  • Twig is not Blade, and form state is not old(). The bundle's template reads Symfony's form view state. Laravel's flash-and-repopulate model is different; empty values and null behave differently in particular. Rewrite the conditionals rather than transliterating them.
  • Version constraints are untested. Zero dependents means nobody has run this against PHP 8.3 / Symfony 7. Check the symfony/form range before you assume composer require in a mixed-stack app is safe.
  • Asset-publishing conventions don't map. Symfony uses Resources/public + assets:install (Assetic or Encore era). Laravel expects Vite with files under resources/. Don't attempt to wire public/vendor publishing; copy the JS/CSS into resources/, import in app.js, and treat it as a vendored dependency pinned in package.json.
  • <input type="color"> might be enough. It's native, accessible-ish, zero-JS, and hex-only. If the bundle's picker adds nothing beyond a palette swatch row, you're paying a dependency for cosmetics. Test the native input first — it's your baseline for "is this worth a library."
  • Platform UI variance is real. Native color inputs render wildly differently across Chrome/Safari/Firefox and mobile. Verify on the browsers your admins actually use before committing to <input type="color">; verify the JS library's a11y (keyboard, screen reader labels) before committing to that.
  • Alpha and format are the usual silent failures. format: 'rgb' produces values your hex regex rejects. If you support alpha, the column grows to 9 chars and your CSS consumers need to handle #RRGGBBAA. Decide once and enforce in the rule.
  • Debug order when nothing renders: (1) is the data-colorpicker attribute actually in the DOM — view-source, not devtools post-init? (2) did the JS bundle load — check the network tab for the entry chunk? (3) is the init selector querying a selector that a Blade {{ $attributes }} merge accidentally overwrote? The missing-data-attribute failure is by far the most common.
  • License is unverified. The README and description don't state it. Confirm via composer.json / LICENSE before vendoring into a client project — this is a legal review item, not a nitpick.
  • Assume unmaintained; plan an owned fork. Zero stars, zero dependents, no release cadence, no advisories. If you adopt the asset, copy it into resources/js/vendor/ with a comment pointing at the source commit. Do not let composer update or npm update be your only supply-chain control.
  • The realistic verdict: the capability belongs on your admin roadmap (settings, tenant branding, tag colors, chart palettes). This specific package is a reference implementation at best. Vendor the JS picker from its upstream, write the Blade component and the validation rule yourself — you get the same result with a license you know, a Vite pipeline that works, and maintenance under your own control.
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.
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen