PHPColor does not expose a semantic-theme generator. Build the workflow from OKLCH construction and contrast checks when your product needs status roles derived from one brand.
Derive the role colors
Keep recognizable status hues and borrow a safe amount of chroma from the brand:
use PhpColor\Color\Color;
$brand = Color::parse('#7c5cff')->to('oklch');
$brandChroma = $brand->getChannels()['c'];
$roles = [
'success' => ['hue' => 145, 'maxChroma' => 0.14],
'warning' => ['hue' => 85, 'maxChroma' => 0.17],
'error' => ['hue' => 25, 'maxChroma' => 0.19],
'info' => ['hue' => 250, 'maxChroma' => 0.15],
];
$colors = [];
foreach ($roles as $name => $role) {
$colors[$name] = Color::oklch(
0.62,
min($brandChroma, $role['maxChroma']),
$role['hue'],
);
}
use PhpColor\Color\Color;
$brand = Color::parse('#7c5cff')->to('oklch');
$brandChroma = $brand->getChannels()['c'];
$roles = [
'success' => ['hue' => 145, 'maxChroma' => 0.14],
'warning' => ['hue' => 85, 'maxChroma' => 0.17],
'error' => ['hue' => 25, 'maxChroma' => 0.19],
'info' => ['hue' => 250, 'maxChroma' => 0.15],
];
$colors = [];
foreach ($roles as $name => $role) {
$colors[$name] = Color::oklch(
0.62,
min($brandChroma, $role['maxChroma']),
$role['hue'],
);
}
Choose an accessible foreground
Test candidates against the final background rather than assuming white text works:
use PhpColor\Color\Color;
use PhpColor\Color\Contrast\ColorContrast;
use PhpColor\Color\Contrast\WcagLevel;
function foregroundFor($background)
{
foreach ([Color::black(), Color::white()] as $candidate) {
if (ColorContrast::meetsFor($candidate, $background, WcagLevel::AA)) {
return $candidate;
}
}
return null;
}
$onWarning = foregroundFor($colors['warning']);
use PhpColor\Color\Color;
use PhpColor\Color\Contrast\ColorContrast;
use PhpColor\Color\Contrast\WcagLevel;
function foregroundFor($background)
{
foreach ([Color::black(), Color::white()] as $candidate) {
if (ColorContrast::meetsFor($candidate, $background, WcagLevel::AA)) {
return $candidate;
}
}
return null;
}
$onWarning = foregroundFor($colors['warning']);
This recipe composes lower-level capabilities; it is not a guarantee that every generated set is in gamut or visually balanced. Verify the serialized output, contrast, and meaning in the product that uses it. Browse the semantic color collection for worked examples.