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

Phpcolors Laravel Package

mexitek/phpcolors

phpColors is a lightweight PHP library for color manipulation: convert between HEX, RGB, and HSL, lighten or darken shades, generate complementary colors, and check contrast. Useful for building palettes, themes, and dynamic CSS without external dependencies.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer — there is no service provider, config file, or facade to register:

composer require mexitek/phpcolors

Everything lives in one class. Instantiate it with a hex string (with or without #) and call the transformation you need:

use Mexitek\PHPColors\Color;

$brand = new Color('336699');

$base   = $brand->getHex();        // "336699"
$hover  = $brand->getDarken(15);   // darker hex for hover state
$active = $brand->getDarken(25);   // darker still for :active
$text   = $brand->getForeground(); // black or white, whichever contrasts

That hover/contrast pair is the first use case worth wiring up: it is the reason most teams pull this package in. A button component needs a darker shade on hover and a readable label color, and both are one call each.

Where to look first:

  • src/Color.php — the entire package. Read it once; it is small enough to finish in a few minutes, and it tells you exactly which methods return a # and which return a plain 6-character string.
  • The README for the method inventory (getDarken, getLighten, getComplementary, getTriad, getTetrad, getAnalogous, getSplitComplementary, getMix, isDark, getForeground, plus static equivalents).
  • The test suite for expected outputs — especially the rounding behavior when a color round-trips through HSL.

Implementation Patterns

Generate a full shade ramp from one brand color. This is the highest-value pattern: turn a single client-supplied color into a design-token scale.

$base = new Color($brandHex);
$scale = [];
foreach ([90, 70, 50, 30, 10] as $i => $step) {
    $scale["brand-{$i}00"] = '#' . $base->getLighten($step);
}

Compute every step from the same base rather than chaining getLighten() calls; chaining compounds the shift (see Gotchas).

Pick readable text on arbitrary backgrounds.

$bg   = new Color($userColor);
$fg   = $bg->isDark() ? '#ffffff' : '#000000';
// or simply:
$fg = $bg->getForeground();

Useful for badges, avatar initials, tag chips, and calendar event blocks where the background is data-driven.

Emit CSS custom properties from a theme record. In a controller, service, or Blade partial:

$theme = [
    'primary'        => $c->getHex(),
    'primary-hover'  => $c->getDarken(12),
    'primary-subtle' => $c->getMix('ffffff', 85),
    'primary-text'   => $c->getForeground(),
];

Then render --color-primary: #{{ $theme['primary'] }}; in a <style> block. This keeps color math out of your CSS build and lets admins reskin an app without a deploy.

Harmonies for categorical data. getComplementary(), getTriad(), getTetrad(), getAnalogous(), and getSplitComplementary() return arrays of hex strings — good for assigning distinct, related series colors in charts or labels in a tag cloud. Cache the result per base color; the array shapes are stable.

Use the static API for one-shot transforms. When you do not need a persistent object, Color::darken($hex, 20), Color::lighten($hex, 20), Color::mix($hex1, $hex2, 50), and Color::isDark($hex) keep call sites short. Reach for the instance API when you are deriving several values from one color.

Normalize at your boundary, not in your views. Wrap the library in a tiny helper or value object that guarantees the leading #, validates input, and falls back to a default brand color. Every Blade template and API response then receives consistently formatted strings, and swapping the library later means editing one file.

Validate user-supplied colors before construction.

$hex = ltrim($request->input('color', '336699'), '#');
if (! Color::isValidHex($hex)) {
    $hex = config('brand.default');
}

Gotchas and Tips

  • Darken/lighten amounts are absolute percentage points on HSL lightness, not multipliers. getDarken(10) subtracts roughly ten points of L. Looping getDarken(5) five times does not equal getDarken(25) and can drive L to zero. Always derive from the original base and clamp your inputs to 0–100.
  • Hash prefix is inconsistent across methods. Most transformations return a bare 6-character hex; some accessors include #. Read src/Color.php once and standardize with a single '#' . ltrim($hex, '#') helper rather than guessing per call site.
  • HSL round-trips drift by a channel value. Converting hex to HSL, rounding, and converting back can produce 336698 where you started with 336699. Do not assert exact string equality in tests against computed shades; assert channel deltas within a tolerance.
  • Only six-digit RGB hex is reliably supported. Three-digit shorthand, rgba(), CSS named colors, and alpha channels are not part of the model. Normalize and expand before constructing.
  • isDark() is a brightness heuristic, not a WCAG contrast calculation. It answers "is this roughly dark?" — getForeground() then picks pure black or pure white. Mid-tone backgrounds can land on a pairing below the 4.5:1 AA ratio. For accessibility-critical UI, compute the real contrast ratio from getRgb() and choose your own foreground, or add a small contrastRatio() helper alongside the library.
  • The constructor does not appear to guard aggressively against malformed input. Call Color::isValidHex() first if the value comes from a user or database; otherwise you get surprising output rather than a clear exception.
  • The package is small and stable, last released in 2021. There are no typed signatures or modern PHP features. It works on recent PHP versions but will emit deprecation noise on 8.x in strict error-reporting setups; pin the version and smoke-test after PHP upgrades.
  • There is no configuration surface. Extension points are limited to subclassing Color (to add withHash(), a contrast helper, or a toCssVar() method) or wrapping it in your own service. Prefer the wrapper — it keeps the library out of your templates.
  • Performance is a non-issue individually but adds up in loops. Generating a 10-step palette per request per component is wasteful; compute tokens once at boot or cache them in config, and memoize per base color inside a request.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource