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

Invert Color Laravel Package

villfa/invert-color

A small PHP package for inverting hex colors. Generate the opposite of any color for contrasting text, hover states, or dark-mode variants, with a simple API that works in plain PHP and Laravel projects alike.

View on GitHub
Deep Wiki
Context7

Getting Started

villfa/invert-color is a single-purpose utility, not a Laravel package in the framework sense: there is no service provider, no facade, no config file, and nothing to publish. Installation is one line and there is no php artisan vendor:publish step:

composer require villfa/invert-color

Where to look first. Before writing any application code, open two things in vendor/villfa/invert-color:

  1. src/ — the main class. Confirm the exact entry point (static invert() vs. an instantiable object), the namespace, and the constructor signature. Small packages like this change shape between majors, and you do not want to guess.
  2. tests/ — the test suite is the de facto documentation. It tells you precisely which input formats are supported (#fff vs #ffffff, uppercase vs. lowercase, whether rgb() strings or alpha channels are accepted) and exactly what the return value looks like.

Also read the composer.json for the php constraint — a package this small is often pinned to a narrow version range, and that determines whether it will survive your next PHP upgrade.

First use case. The natural fit is dynamic theming: you have a user- or tenant-supplied brand color stored in the database and you need a derived color for a contrasting element — a badge background, an avatar fallback, a hover state, a border. Instead of shipping a lookup table of hardcoded pairs, compute the inverted color at render time:

use Villfa\InvertColor\InvertColor; // verify namespace in src/

$inverted = InvertColor::invert($tenant->brand_color); // '#3366cc' -> '#cc9933'

That is the whole package. Everything below is about wrapping it sensibly so a 30-line utility does not leak into forty Blade templates.

Implementation Patterns

Wrap it in an application-level service. The single most valuable thing you can do with a package this small is to not call it directly from views. Define a thin adapter so the dependency is swappable and mockable:

namespace App\Support;

use Villfa\InvertColor\InvertColor;

class ColorService
{
    public function invert(string $hex): string
    {
        return InvertColor::invert($this->normalize($hex));
    }

    protected function normalize(string $hex): string
    {
        $hex = ltrim(trim($hex), '#');
        if (strlen($hex) === 3) {
            $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
        }
        return '#'.strtolower($hex);
    }
}

Normalizing in your layer rather than trusting the package means an upgrade that changes shorthand handling won't silently break your UI. Bind it as a singleton in AppServiceProvider only if you add caching or config to it; otherwise plain resolution is fine.

Blade usage via a directive. Register once, use everywhere:

// AppServiceProvider::boot()
Blade::directive('invertColor', fn ($expr) => "<?php echo e(app(\App\Support\ColorService::class)->invert($expr)); ?>");
<span style="background: {{ $tenant->brand_color }}; color: @invertColor($tenant->brand_color)">
    {{ $tenant->name }}
</span>

Model accessor for persisted derivation. If the inverted color is used in more than one place, compute it once on write rather than on every render. An accessor keeps it lazy; an saving observer keeps it queryable and indexable:

protected function contrastColor(): Attribute
{
    return Attribute::make(fn () => app(ColorService::class)->invert($this->brand_color));
}

Build-time palette generation. For anything static — a design-token CSS file, a Filament/Nova theme, an email template — generate the values in an Artisan command and commit or cache the output. This removes the package from the request path entirely and makes the runtime dependency irrelevant:

foreach (config('brand.palette') as $name => $hex) {
    $lines[] = "--brand-{$name}-inverse: {$service->invert($hex)};";
}
File::put(resource_path('css/tokens.css'), ":root {\n".implode("\n", $lines)."\n}");

Testing pattern. Because the output is a deterministic string, assert on exact values, not on assertNotEquals. Run the normalization layer through a data provider covering #fff, fff, #FFFFFF, and a value with stray whitespace from a form submission.

Gotchas and Tips

Inversion is not contrast. This is the trap that catches almost everyone. Inverting a color in RGB space is not the same as guaranteeing readable text. Mid-grays are the failure case: inverting #808080 yields something within a single bit of itself, so dark-gray text on a mid-gray badge stays unreadable. If your actual goal is WCAG-safe foreground/background pairing, this package is the wrong tool — implement a relative-luminance check and pick black or white. Use invert-color when you want a stylistically paired accent, not an accessible one.

Hue flips too. #ff0000 becomes #00ffff. That is mathematically correct and visually jarring if your brand guidelines assume the derived color stays in the same family. If you want "same hue, lighter/darker," you need an HSL round-trip, not an RGB complement.

Verify input tolerance before shipping. Small utility packages frequently reject the leading #, or reject three-digit shorthand, or throw on anything non-hex rather than returning null. Confirm against tests/ and treat the package as strict — do all cleaning in your adapter. The most common production failure here is invisible whitespace from a form field or a .env value (BRAND_COLOR="#3366cc ") causing an exception in a Blade render and a 500 on a page that has nothing to do with color.

Output casing and prefix are not guaranteed. Do not concatenate the result into a string that assumes a #, and do not compare it case-sensitively against stored values. Normalize on the way out of your service too, especially if you are writing the result into a database column with a unique index.

No config means no knobs. There is nothing to tune, no config/invert-color.php, no facade alias to add to config/app.php. If you find yourself wanting options — alpha preservation, HSL mode, named-color support — you have outgrown the package. Write the ~20 lines yourself; RGB inversion is 255 - $channel per channel.

Abandonment risk is real and cheap to mitigate. Fifteen stars, zero dependents, no config surface. If you are uncomfortable relying on it, the honest options are (a) fork it into app/Support and drop the Composer dependency, or (b) pin the exact version in composer.json with "villfa/invert-color": "1.0.*" rather than a caret constraint, so a surprise major release cannot change return formatting under you. For a package this small, vendoring is a legitimate and low-cost choice — and it makes the code reviewable by anyone on the team.

Debugging checklist. When the output looks wrong: dd($input) immediately before the call to catch whitespace and type coercion (an integer 0x3366cc cast to string behaves differently from a hex string); confirm you are not double-inverting (an accessor plus a Blade directive that both invert will return the original color and look like the package is a no-op); and check that the CSS you are generating is not being overridden by a more specific selector, which reads as "the inversion didn't apply."

Extension points are limited by design. There is no interface to implement and no driver to swap. The only clean seam is your own ColorService — which is exactly why the first pattern in this document is the wrapper. Treat the package as an implementation detail behind that seam and an eventual replacement costs one file.

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.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk