Extract the scheme stylesheet shape for ErrorPage to reuse
SchemeCommand::levels()/selectors()/blocks() move to a new SchemeStylesheet, and Scheme gains forStylesheet(), which resolves a scheme (and every profile) at all three contrast levels together. Plan step 40's fallback needs to draw the same colours material:scheme writes, without duplicating its selector logic. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
513e344912
commit
3b9a889e7c
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace NoNameWeb\LivewireMaterial\Support;
|
||||
|
||||
/**
|
||||
* The selector shape a Material 3 colour scheme is written in: the standard level on `:root` and
|
||||
* `[data-theme]` (or, under a prefix, repeated so it still reaches a theme set on `<html>` or on a
|
||||
* nested panel), the medium and high contrast levels under `[data-contrast]` beside it, and — when
|
||||
* a caller gives one — every colour profile again under its own prefix (`[data-scheme='name']`).
|
||||
*
|
||||
* `SchemeCommand::handle()` writes this to the application's `material-scheme.css`; plan step 40
|
||||
* moved the shape itself here so `ErrorPage::fallbackStyles()` can draw the same scheme, from
|
||||
* `Scheme::forStylesheet()` rather than a generated file, without a second copy of the selectors to
|
||||
* keep in step with the command's.
|
||||
*/
|
||||
final class SchemeStylesheet
|
||||
{
|
||||
/**
|
||||
* M3's two contrast levels beyond standard, keyed on `<html data-contrast>`; standard is the
|
||||
* scheme's own level and has no attribute of its own.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
public const array LEVELS = ['medium', 'high'];
|
||||
|
||||
/**
|
||||
* One scheme, whole: the standard level first, under `$prefix` (or `:root`/`[data-theme]`
|
||||
* without one), then M3's medium and high levels under `[data-contrast]` beside it. A level's
|
||||
* blocks are the standard ones with one more attribute, so they outrank them wherever both
|
||||
* match, and the light blocks of a level come before its dark ones as in every other pair here.
|
||||
*
|
||||
* @param array{contrast: array<string, array{light: array<string, string>, dark: array<string, string>}>, light: array<string, string>, dark: array<string, string>} $scheme
|
||||
*/
|
||||
public static function levels(array $scheme, string $prefix = ''): string
|
||||
{
|
||||
[$light, $dark] = self::selectors($prefix);
|
||||
|
||||
$css = self::blocks($light, $dark, $scheme);
|
||||
|
||||
foreach (self::LEVELS as $level) {
|
||||
[$light, $dark] = self::selectors($prefix."[data-contrast='{$level}']");
|
||||
|
||||
/** @var array{light: array<string, string>, dark: array<string, string>} $roles */
|
||||
$roles = $scheme['contrast'][$level];
|
||||
|
||||
$css .= "\n".self::blocks($light, $dark, $roles);
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* The light and the dark selectors of one block, under the given prefix. Without a prefix the
|
||||
* plain blocks stand on `:root` and on the attribute alone; with one, the prefix is on `<html>`
|
||||
* and the theme may be on `<html>` or on a panel inside it, so both forms are written.
|
||||
*
|
||||
* @return array{list<string>, list<string>}
|
||||
*/
|
||||
public static function selectors(string $prefix): array
|
||||
{
|
||||
if ($prefix === '') {
|
||||
return [[':root', "[data-theme='light']"], ["[data-theme='dark']"]];
|
||||
}
|
||||
|
||||
return [
|
||||
[$prefix, "{$prefix}[data-theme='light']", "{$prefix} [data-theme='light']"],
|
||||
["{$prefix}[data-theme='dark']", "{$prefix} [data-theme='dark']"],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* A light and a dark block of roles under the given selectors.
|
||||
*
|
||||
* @param list<string> $light
|
||||
* @param list<string> $dark
|
||||
* @param array{light: array<string, string>, dark: array<string, string>} $scheme
|
||||
*/
|
||||
public static function blocks(array $light, array $dark, array $scheme): string
|
||||
{
|
||||
$roles = fn (array $roles): string => collect($roles)
|
||||
->map(fn (string $hex, string $role): string => " --md-sys-color-{$role}: {$hex};")
|
||||
->implode("\n");
|
||||
|
||||
return implode(",\n", $light)." {\n color-scheme: light;\n\n".$roles($scheme['light'])."\n}\n\n"
|
||||
.implode(",\n", $dark)." {\n color-scheme: dark;\n\n".$roles($scheme['dark'])."\n}\n";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user