jimigrunge/bootstrap-colorpicker-bundle
A Symfony bundle that integrates bootstrap-colorpicker into your Twig templates, giving you a simple reusable form component for adding Bootstrap-styled color pickers to your application's forms.
The first thing to understand is that this is not a Laravel package. jimigrunge/bootstrap-colorpicker-bundle is a Symfony2 bundle (circa 2014–2016) that wraps the mjolnic/bootstrap-colorpicker jQuery plugin. It registers assets through Assetic and (typically) exposes a Twig form type. With 2 stars, 0 dependents, a NOASSERTION license, and a hard dependency on Symfony2's now-removed Assetic pipeline, you cannot composer require it into a Laravel app and expect anything to happen. Treat the repo as documentation for a pattern, not a dependency.
What you actually want is the underlying plugin, which is what does 100% of the work anyway:
npm install bootstrap-colorpicker@^3.4.0
# jQuery is a peer dependency
npm install jquery
Where to look first:
github.com/mjolnic/bootstrap-colorpicker (the bundle adds nothing you can't read there).resources/js/bootstrap.js in your Laravel app — this is where jQuery and plugin registration belong.Resources/views/ and Resources/public/ folders if you're curious about the Twig form-type pattern, which maps cleanly onto a Blade component.Minimal first use case — a hex color field in a settings form:
// resources/js/bootstrap.js
import $ from 'jquery';
window.$ = window.jQuery = $;
import 'bootstrap-colorpicker';
import 'bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css';
{{-- resources/views/components/color-input.blade.php --}}
@props(['name', 'value' => '#563d7c'])
<input
type="text"
name="{{ $name }}"
id="{{ $name }}"
value="{{ old($name, $value) }}"
{{ $attributes->merge(['class' => 'form-control']) }}
data-colorpicker
/>
document.querySelectorAll('[data-colorpicker]').forEach((el) => {
$(el).colorpicker({ format: 'hex' });
});
That's the whole "bundle" in about fifteen lines.
Bundle the CSS through Vite, not a CDN. The plugin ships a Sprite-based PNG for the saturation/picker dials; if you load only the JS you'll get an invisible picker with a working input. Import the CSS in your entrypoint so Vite rewrites the asset URLs.
Blade component + @push for one-time init. If you render a picker inside a partial that can appear many times, initialize once at the page level rather than per-component:
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', () => {
$('[data-colorpicker]').colorpicker({
format: 'hex',
color: undefined, // let the input's value win
popover: { container: 'body' },
});
});
</script>
@endpush
popover.container: 'body' is the single most useful option — it solves the "picker clipped by overflow: hidden" problem inside cards, tables, and modals.
Livewire integration. jQuery mutates the input's value but does not fire a native input event, so wire:model won't pick it up. Bind the plugin's event explicitly:
<input
type="text"
wire:model.defer="accent_color"
x-data
x-init="$($el).colorpicker({ format: 'hex' })
.on('changeColor', (e) => $el.value = e.color.toString('hex'))"
/>
Two caveats: x-init requires Alpine, and after a Livewire re-render (wire:model updating elsewhere) the DOM node may be replaced and the picker destroyed. Use wire:ignore on the input wrapper if the value is only touched by the user.
Alpine wrapper component. Cleaner than scattered jQuery:
Alpine.data('colorPicker', (initial = '#000000') => ({
value: initial,
init() {
const picker = $(this.$el.querySelector('input'))
.colorpicker({ format: 'hex' })
.on('changeColor', (e) => {
this.value = e.color.toString('hex');
this.$dispatch('color-changed', { value: this.value });
});
this.$watch('value', (v) => picker.colorpicker('setValue', v));
},
}));
Note the re-entrancy risk: setValue fires changeColor, which sets this.value, which triggers $watch. Guard with a flag or compare-before-set if you see an infinite loop.
Dynamic rows. Any picker added after page load needs its own init. If you're using Alpine x-for this is automatic (each iteration runs x-init); if you're using jQuery .append() you must call .colorpicker() on the new element manually.
Server-side validation is mandatory. Everything the plugin produces is a string the user could have typed by hand — the picker is a UI convenience, not a validator.
$request->validate([
'accent_color' => ['required', 'string', 'regex:/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/'],
]);
Normalize before persisting (strtolower, expand 3-digit hex, or store rgb()/HSL as your schema dictates) so that #FFF, #ffffff, and rgb(255,255,255) don't become three different DB values.
Storage. Hex strings in a char(7) column are the pragmatic default. If you need alpha, store #rrggbbaa and be explicit about it — the plugin's format: 'rgba' output is not what most people expect in a "color" column.
composer require jimigrunge/bootstrap-colorpicker-bundle will fail or drag in Symfony2/Assetic-era constraints that conflict with any modern Laravel app. There is no Laravel service provider, no facade, no config publish — the "integration" simply doesn't exist.JimiGrünge\… (with ü). This has historically caused PSR-4 autoloading and filesystem-encoding problems on Windows and in some CI images — another reason not to vendor the PHP side.NOASSERTION. GitHub could not detect a license file. That means the bundle is legally "all rights reserved" by default even though the underlying plugin is MIT (or Apache-2.0 depending on version). If your legal team cares, depend on mjolnic/bootstrap-colorpicker directly and cite its license; do not copy code out of the bundle.bootstrap-colorpicker v3 requires jQuery; there is no vanilla-JS build and no maintained React/Vue/Alpine port from the original author. For a modern Laravel app that has otherwise removed jQuery, this is a real cost — weigh it against a small native <input type="color"> or a lightweight vanilla picker.changeColor vs colorpicker-change. Event names differ across versions. If your handler silently never fires, log $(el).data('colorpicker') and check the installed version's docs rather than guessing..colorpicker('setValue', '#abc') may normalize to #aabbcc, and getValue/color.toString() differ from the raw input value. Always read from the plugin API, not el.value, if you've set a non-hex format.overflow: hidden (→ popover.container: 'body'), (5) are there two copies of jQuery on the page.How can I help you explore Laravel packages today?