diff --git a/resources/css/showcase.css b/resources/css/showcase.css index e5c4af89..7cc95e78 100644 --- a/resources/css/showcase.css +++ b/resources/css/showcase.css @@ -16,6 +16,12 @@ * selector this file needs to draw over, only tokens already in `all.css`, which the bundle always * carries ahead of this file. A later batch that needs a component's own hook imports its * stylesheet here, as every other package file does. + * + * Batch 2 (the foundation and layout sections) adds the swatches, specimens and demo boxes those + * pages draw beyond a layout component and a `md-*` text class: a colour swatch (its own fill is + * the role it shows, so that one declaration is the caller's inline `style`, never a class), a + * type-scale row, a shape swatch, an elevation tile, a motion track and its moving dot, an icon + * search result and the Layout page's breakpoint cards. */ @layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility; @@ -114,4 +120,26 @@ background-color: var(--md-sys-color-surface-container-highest); padding: var(--md-sys-measurement-space125); } + + /* Colour: a role swatch. Its fill is the one declaration that has to be the caller's inline + `style` (the role it shows decides it), so this rule only gives it a size and an edge; `lg` + is the big per-theme grid's, the plain attribute the smaller contrast-level list's. */ + [data-md-showcase-swatch] { + display: block; + flex-shrink: 0; + width: var(--md-sys-measurement-space300); + height: var(--md-sys-measurement-space300); + border-radius: var(--md-sys-shape-corner-xs); + border: 1px solid var(--md-sys-color-outline-variant); + } + + [data-md-showcase-swatch][data-md-showcase-size='lg'] { + width: var(--md-sys-measurement-space400); + height: var(--md-sys-measurement-space400); + } + + /* Lets the role name beside a swatch ellipsize inside its row instead of widening the grid. */ + [data-md-showcase-swatch-label] { + min-width: 0; + } } diff --git a/resources/views/showcase/sections/colour.blade.php b/resources/views/showcase/sections/colour.blade.php index c240d608..d441c608 100644 --- a/resources/views/showcase/sections/colour.blade.php +++ b/resources/views/showcase/sections/colour.blade.php @@ -1,25 +1,24 @@ @php $groups = [ - 'Primary' => ['bg-primary', 'bg-on-primary', 'bg-primary-container', 'bg-on-primary-container', 'bg-inverse-primary', 'bg-primary-fixed', 'bg-primary-fixed-dim', 'bg-on-primary-fixed', 'bg-on-primary-fixed-variant'], - 'Secondary' => ['bg-secondary', 'bg-on-secondary', 'bg-secondary-container', 'bg-on-secondary-container', 'bg-secondary-fixed', 'bg-secondary-fixed-dim', 'bg-on-secondary-fixed', 'bg-on-secondary-fixed-variant'], - 'Tertiary' => ['bg-tertiary', 'bg-on-tertiary', 'bg-tertiary-container', 'bg-on-tertiary-container', 'bg-tertiary-fixed', 'bg-tertiary-fixed-dim', 'bg-on-tertiary-fixed', 'bg-on-tertiary-fixed-variant'], - 'Error' => ['bg-error', 'bg-on-error', 'bg-error-container', 'bg-on-error-container', 'bg-inverse-error'], - 'Success' => ['bg-success', 'bg-on-success', 'bg-success-container', 'bg-on-success-container', 'bg-inverse-success'], - 'Warning' => ['bg-warning', 'bg-on-warning', 'bg-warning-container', 'bg-on-warning-container', 'bg-inverse-warning'], - 'Info' => ['bg-info', 'bg-on-info', 'bg-info-container', 'bg-on-info-container', 'bg-inverse-info'], - 'Surface' => ['bg-surface', 'bg-surface-dim', 'bg-surface-bright', 'bg-surface-container-lowest', 'bg-surface-container-low', 'bg-surface-container', 'bg-surface-container-high', 'bg-surface-container-highest', 'bg-on-surface', 'bg-on-surface-variant', 'bg-inverse-surface', 'bg-inverse-on-surface', 'bg-outline', 'bg-outline-variant'], - 'Ink and lines' => ['bg-body', 'bg-meta', 'bg-quiet', 'bg-structure', 'bg-chrome', 'bg-divider'], + 'Primary' => ['primary', 'on-primary', 'primary-container', 'on-primary-container', 'inverse-primary', 'primary-fixed', 'primary-fixed-dim', 'on-primary-fixed', 'on-primary-fixed-variant'], + 'Secondary' => ['secondary', 'on-secondary', 'secondary-container', 'on-secondary-container', 'secondary-fixed', 'secondary-fixed-dim', 'on-secondary-fixed', 'on-secondary-fixed-variant'], + 'Tertiary' => ['tertiary', 'on-tertiary', 'tertiary-container', 'on-tertiary-container', 'tertiary-fixed', 'tertiary-fixed-dim', 'on-tertiary-fixed', 'on-tertiary-fixed-variant'], + 'Error' => ['error', 'on-error', 'error-container', 'on-error-container', 'inverse-error'], + 'Success' => ['success', 'on-success', 'success-container', 'on-success-container', 'inverse-success'], + 'Warning' => ['warning', 'on-warning', 'warning-container', 'on-warning-container', 'inverse-warning'], + 'Info' => ['info', 'on-info', 'info-container', 'on-info-container', 'inverse-info'], + 'Surface' => ['surface', 'surface-dim', 'surface-bright', 'surface-container-lowest', 'surface-container-low', 'surface-container', 'surface-container-high', 'surface-container-highest', 'on-surface', 'on-surface-variant', 'inverse-surface', 'inverse-on-surface', 'outline', 'outline-variant'], ]; // The roles a contrast level moves most: the page keeps its surface, the ink and the // outlines carry the level. $levels = ['standard' => 'Standard', 'medium' => 'Medium · 3:1', 'high' => 'High · 7:1']; - $levelRoles = ['bg-primary', 'bg-on-primary', 'bg-primary-container', 'bg-on-primary-container', 'bg-on-surface-variant', 'bg-outline', 'bg-error', 'bg-success', 'bg-warning', 'bg-info']; + $levelRoles = ['primary', 'on-primary', 'primary-container', 'on-primary-container', 'on-surface-variant', 'outline', 'error', 'success', 'warning', 'info']; $profile = \NoNameWeb\LivewireMaterial\Support\Scheme::profile(); $examples = [ 'Colour profiles' => <<<'BLADE' -
+
BLADE, @@ -29,25 +28,25 @@ ]; @endphp -
-

Colour

+ +

Colour

-

- Every role as bg-*, text-* and border-*, generated by +

+ Every role as a --md-sys-color-* token, generated by php artisan material:scheme. Both themes side by side, whatever the page is showing.

-

+

When to use which: primary is the one key action on a screen; secondary-container is the quiet fill (tonal buttons, selected navigation and chips); tertiary is a rare accent; error, success, warning and info mean state — the -container for a tinted panel, the role itself for its text and icon. Pair a role only with its on- partner. Ink is on-surface, lower emphasis on-surface-variant, decoration outline; never an opacity, because 38% means disabled. Every role changes with the contrast level below, which is why only roles are allowed.

-

+

With colour profiles in livewire-material.profiles, the command generates each one under <html data-scheme>, and <x-scheme-picker> chooses between them. Without profiles the picker draws nothing.

-

+

Every scheme is generated at M3's three contrast levels — standard, medium (3:1) and high (7:1) — and the head script writes the visitor's to <html data-contrast>, following the operating system until they choose. The page keeps its surface; the ink, the outlines and the containers carry the level. @@ -57,53 +56,57 @@ @endforeach -

+ @foreach ($levels as $level => $title) {{-- data-scheme beside data-contrast: a profile's level blocks key on both attributes together, as they do on . --}} -
-

{{ $title }}

+

{{ $title }}

@foreach (['light', 'dark'] as $theme) -
-

{{ $theme }}

+ + +

{{ ucfirst($theme) }}

- @foreach ($levelRoles as $role) -
- - {{ \Illuminate\Support\Str::after($role, 'bg-') }} -
- @endforeach -
- @endforeach -
- @endforeach -
- -
- @foreach (['light', 'dark'] as $theme) -
-

{{ $theme }}

- - @foreach ($groups as $group => $roles) -
-

{{ $group }}

- -
- @foreach ($roles as $role) -
- - {{ \Illuminate\Support\Str::after($role, 'bg-') }} -
+ @foreach ($levelRoles as $role) + + + {{ $role }} + @endforeach -
-
+ + @endforeach -
+ @endforeach -
-
+ + + + @foreach (['light', 'dark'] as $theme) + + +

{{ ucfirst($theme) }}

+ + @foreach ($groups as $group => $roles) + +

{{ $group }}

+ + + @foreach ($roles as $role) + + + {{ $role }} + + @endforeach + +
+ @endforeach +
+
+ @endforeach +
+ diff --git a/tests/Browser/ColourProfilesTest.php b/tests/Browser/ColourProfilesTest.php index 2f85fd3a..3987d755 100644 --- a/tests/Browser/ColourProfilesTest.php +++ b/tests/Browser/ColourProfilesTest.php @@ -54,7 +54,7 @@ it('draws each profile in light and dark, and the default without the attribute' $page->script("document.documentElement.setAttribute('data-theme', 'dark')"); $page->assertScript(pagePrimary()." === '{$this->profiles['teal']['dark']['primary']}'") // A panel that sets its own theme keeps the page's profile. - ->assertScript("getComputedStyle(document.querySelector('#colour [data-theme=\"light\"] .bg-primary')).backgroundColor === '".rgb($this->profiles['teal']['light']['primary'])."'"); + ->assertScript("getComputedStyle(document.querySelector('#colour [data-theme=\"light\"] [data-md-showcase-swatch=\"primary\"]')).backgroundColor === '".rgb($this->profiles['teal']['light']['primary'])."'"); $page->script("document.documentElement.removeAttribute('data-scheme')"); $page->assertScript(pagePrimary()." === '{$this->profiles['baseline']['dark']['primary']}'") diff --git a/tests/Browser/ThemeTest.php b/tests/Browser/ThemeTest.php index c0f387ce..a7657b45 100644 --- a/tests/Browser/ThemeTest.php +++ b/tests/Browser/ThemeTest.php @@ -56,7 +56,7 @@ it('adopts an earlier toggle\'s choice once', function () { }); it('repaints a section that sets its own theme', function () { - $swatch = fn (int $index): string => "getComputedStyle(document.querySelectorAll('#colour [data-theme] .bg-primary')[{$index}]).backgroundColor"; + $swatch = fn (int $index): string => "getComputedStyle(document.querySelectorAll('#colour [data-theme] [data-md-showcase-swatch=\"primary\"]')[{$index}]).backgroundColor"; visit('/material/colour')->inLightMode() ->assertScript(theme('data-theme', 'light'))