Give success, warning and info the 2025 spec and three contrast levels
The three state colours are DynamicColors on their own tonal palette now, built exactly as Google builds error/on-error/error-container/on-error-container in both specs, so the scheme's contrast level, dark tones, spec version and platform reach them as they reach every other role; --harmonize (and a profile's harmonize) pulls each source towards the seed, off by default. material:scheme also writes M3's medium (0.5) and high (1.0) levels for both themes and every profile, keyed on data-contrast and never on a media query, and --contrast now moves the standard block alone. Scheme::load() takes the level; the mail theme stays on standard. Plan: docs/plans/material-3-alignment.md, steps 6 and 7 (core C1, C2, C15). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
b1fc0c9cfa
commit
4263982369
@@ -19,6 +19,11 @@ function writeProfiles(string $path, array $primaries, string $default): void
|
||||
'contrast' => 0,
|
||||
'light' => ['primary' => $primary, 'surface' => '#fafafa'],
|
||||
'dark' => ['primary' => '#eeeeee', 'surface' => '#111111'],
|
||||
'contrast' => [
|
||||
'standard' => 0,
|
||||
'medium' => ['light' => ['primary' => '#332f8a'], 'dark' => ['surface' => '#0a0a0a']],
|
||||
'high' => ['light' => ['primary' => '#000000'], 'dark' => ['primary' => '#ffffff', 'surface' => '#000000']],
|
||||
],
|
||||
])->all();
|
||||
|
||||
File::put($path, json_encode([...collect($profiles[$default])->except('label')->all(), 'default' => $default, 'profiles' => $profiles]));
|
||||
@@ -69,6 +74,29 @@ it('loads a profile by name, whatever is active', function () {
|
||||
->and(Scheme::light($this->path, 'ocean')['primary'])->toBe('#00897b');
|
||||
});
|
||||
|
||||
it('loads a contrast level, falling back to the standard roles it does not name', function () {
|
||||
expect(Scheme::load($this->path, 'teal', 'high')['light']['primary'])->toBe('#000000')
|
||||
->and(Scheme::load($this->path, 'teal', 'high')['dark']['surface'])->toBe('#000000')
|
||||
// The level names no surface in light, so the standard one stands.
|
||||
->and(Scheme::light($this->path, 'teal', 'high')['surface'])->toBe('#fafafa')
|
||||
->and(Scheme::load($this->path, 'teal', 'medium')['light']['primary'])->toBe('#332f8a')
|
||||
->and(Scheme::load($this->path, 'teal')['light']['primary'])->toBe('#00897b')
|
||||
// A level nobody generated, and a name that is not one, are the standard scheme.
|
||||
->and(Scheme::load($this->path, 'teal', 'extreme')['light']['primary'])->toBe('#00897b')
|
||||
->and(Scheme::profiles($this->path, 'high')['rose']['light']['primary'])->toBe('#000000')
|
||||
->and(Scheme::profiles($this->path)['rose']['light']['primary'])->toBe('#c2185b');
|
||||
});
|
||||
|
||||
it('draws a high contrast level from the package default for a scheme file without one', function () {
|
||||
File::put($this->path, json_encode(['light' => ['primary' => '#123456'], 'dark' => ['primary' => '#abcdef']]));
|
||||
|
||||
$package = json_decode(File::get(__DIR__.'/../../resources/css/tokens/scheme.json'), true);
|
||||
|
||||
expect(Scheme::light($this->path, null, 'high')['primary'])->toBe('#123456')
|
||||
->and(Scheme::light($this->path, null, 'high')['surface'])->toBe($package['contrast']['high']['light']['surface'])
|
||||
->and(Scheme::light($this->path)['surface'])->toBe($package['light']['surface']);
|
||||
});
|
||||
|
||||
it('has no profile for a single scheme, and loads it as before', function () {
|
||||
File::put($this->path, json_encode(['light' => ['primary' => '#123456'], 'dark' => ['primary' => '#abcdef']]));
|
||||
Scheme::resolveProfileUsing(fn (): string => 'teal');
|
||||
|
||||
Reference in New Issue
Block a user