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 Laravel Package

primal/color

primal/color is a PHP package for working with colors in Laravel and other PHP apps, offering helpers to convert between formats like hex, RGB, and HSL, adjust shades and brightness, and generate or manipulate palettes with a simple, expressive API.

View on GitHub
Deep Wiki
Context7

Getting Started

primal/color is a plain PHP color-conversion/manipulation library — there is no Laravel service provider, facade, or config file to publish. Installation is a single Composer require:

composer require primal/color

The classes are namespaced under Primal\Color\ and autoload via PSR-4, so once installed there is nothing else to register.

Where to look first: open vendor/primal/color/src/ and skim the class list before writing any code. The public surface is small: a parser/entry point (typically Primal\Color\Parser) that turns a string like #3498db, rgb(52,152,219), or hsl(204,70%,53%) into a color object, plus one class per color model (RGBColor, HSLColor, etc.) with conversion and manipulation methods (toRGB(), toHSL(), toHexString(), lighten(), darken(), saturate(), …). Because documentation is thin, the source is the spec — confirm exact method names, argument ranges (0–1 vs 0–100 for HSL), and whether operations mutate the object or return a clone.

First use case — normalizing a user-supplied brand color and deriving a hover state:

use Primal\Color\Parser;

$base  = Parser::parse($request->input('brand_color'));   // e.g. "#3498db"
$hover = (clone $base)->darken(10);                        // check mutate-vs-return semantics

return response()->json([
    'base'  => $base->toHexString(),
    'hover' => $hover->toHexString(),
]);

That covers 80% of day-to-day usage: accept a color in any common notation, canonicalize it to hex, and produce a small set of derived shades.

Implementation Patterns

Wrap it in one app-level helper. Given the low star count and single-maintainer status, do not call Primal\Color\* from controllers, Blade templates, or models. Create a thin App\Support\Color (or a ColorService in a small package of your own) that exposes only what you use:

namespace App\Support;

use Primal\Color\Parser;

final class Color
{
    public static function hex(string $value): string
    {
        return Parser::parse($value)->toHexString();
    }

    public static function shade(string $value, int $percent): string
    {
        return (clone Parser::parse($value))->darken($percent)->toHexString();
    }

    public static function palette(string $base, int $steps): array { /* … */ }
}

Everything downstream talks to App\Support\Color. Swapping to league/color or spatie/color later becomes a one-file change.

Theme / CSS variable generation. A view composer or a cached config value that emits CSS custom properties is the highest-value integration:

// AppServiceProvider::boot()
View::composer('layouts.app', function ($view) {
    $brand = Setting::get('brand_color', '#3498db');

    $view->with('theme', Cache::rememberForever("theme.$brand", fn () => [
        '--brand'        => Color::hex($brand),
        '--brand-hover'  => Color::shade($brand, 10),
        '--brand-subtle' => Color::shade($brand, -80),
    ]));
});

Validation. Replace regex-based color validation with parse-and-catch — it accepts #abc, #aabbcc, rgb(), hsl(), and named colors in one rule, and gives you the canonical form for free:

'brand_color' => ['required', 'string', function ($attr, $value, $fail) {
    try { Color::hex($value); }
    catch (\Throwable $e) { $fail('The :attribute must be a valid color.'); }
}],

Deterministic placeholder / avatar colors. Hash a stable key (user id, initials, slug) into a hue, build an HSL color, convert to hex. This gives consistent per-entity colors with no storage:

$hue = crc32($user->email) % 360;
$hex = Parser::parse("hsl($hue,65%,55%)")->toRGB()->toHexString();

Chart / categorical series. Take a base color and walk the hue or lightness axis per series index, clamping saturation so nothing goes muddy. Cache the resulting array — charts tend to render the same palette on every request.

Model casts and API resources. Store colors as canonical hex strings in the DB ($table->string('brand_color', 7)), cast on the way out through your helper, and never store the package's objects directly (they aren't reliably JSON-serializable).

Accessibility pass. Before applying a derived color as text-on-background, compute relative luminance / contrast and flip to a dark or light variant if it fails. If the library's luminance or contrast helpers are missing or under-documented, implement the WCAG formula in your helper rather than fighting the package.

Gotchas and Tips

  • No facade, no provider. Color::make() does not exist. If you want Color:: in Blade, that's your facade wrapping your helper class.
  • License is NOASSERTION. No machine-readable license file was detected. Treat it as unknown until a human reads LICENSE/composer.json. For a commercial product this is a real blocker — get sign-off or vendor a permissively licensed alternative before shipping.
  • Pin the version. Last release was mid-2023, ~24 stars, one maintainer, zero dependents. Use "primal/color": "1.0.*" (exact minor), commit the lockfile, and let your wrapper isolate the blast radius.
  • Mutability is ambiguous. Some color libraries return new instances from lighten()/darken(), others mutate in place. Test this explicitly before chaining; (clone $color) before manipulation is cheap insurance.
  • Round-trip drift. Hex ↔ HSL ↔ RGB conversions involve rounding, and hex cannot hold alpha. Don't assert exact equality on round trips in tests — assert within a tolerance of ±1 per channel, and keep the original string if alpha matters.
  • Output formatting is not normalized for you. Case (#FF0000 vs #ff0000), leading #, and shorthand (#f00) may pass straight through. Canonicalize once in your helper and be consistent everywhere; otherwise DB comparisons and cache keys silently diverge.
  • HSL manipulation is not perceptually uniform. darken(10) in HSL space produces uneven results across hues — yellows get muddy faster than blues. For anything user-facing and contrast-sensitive, derive shades via luminance/Lab math rather than naive HSL lightness steps.
  • Argument ranges. Confirm whether saturation/lightness/lighten amounts are 0–1 or 0–100, and whether they're relative or absolute. A lighten(10) that means 10 percentage points vs 10% is a common source of "why is this white?" bugs.
  • Invalid input throws. Parser::parse() will not return null for garbage — wrap it in try/catch at every boundary where user input enters, and never let a stored bad value 500 a page render (guard the theme composer).
  • No color naming or nearest-match. You won't get "this is basically rebeccapurple" out of the box. If you need it, store your own name→hex table and do distance matching yourself.
  • Parsing is cheap but not free. In a loop over 500 rows generating a palette per row you'll notice it. Memoize parsed objects in a static array keyed by input string, or cache the derived palette wholesale.
  • Extension point is inheritance. Add your own converter by extending the base Color class or composing your helper around the package's outputs. The codebase is small enough (a handful of classes) that forking or vendoring is a realistic option if the package stalls — another reason to keep the dependency behind one wrapper class.
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