Keep a list row's fill under its state layer

Plan step 36 review of 9ff5a7a8. The rewrite dropped the unlayered
selected rule into material.components beside the segmented fill and the
row tint, so on equal or greater weight a selected item in a segmented
list drew surface instead of secondary-container, and hovering, pressing
or focusing any selected row (or a table's selected row) swapped its
fill for a translucent tint. Each fill now names itself
--md-list-row-fill, and the row's layer is its ink mixed over that fill
at the state tokens, which is also C-08's second suggested fix.

A disabled item inks the whole row at the disabled-content token, as the
old root colour did, so the check, the leading slot and the end slot dim
with the text; the three-line padding is a literal 12px like alert.css;
list-rows.js named list.css.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-14 22:00:03 +02:00
co-authored by Claude Opus 5
parent a8c2d88fbb
commit 7d3abdd506
4 changed files with 68 additions and 20 deletions
+28
View File
@@ -1,5 +1,6 @@
<?php
use Illuminate\Support\Facades\File;
use NoNameWeb\LivewireMaterial\Tests\Support\ComponentStylesheet;
it('draws a plain list, with dividers on request', function () {
@@ -113,3 +114,30 @@ it('leads with M3\'s video, in the size the item\'s height calls for', function
->not->toContain('data-md-list-item-video')
->toContain('data-md-lines="1"');
});
it('lays a row\'s state layer over its fill, so a selected or segmented row keeps its colour under the tint', function () {
$css = ComponentStylesheet::read('list-item');
$hover = '[data-md-list-row]:not([data-md-card]):hover:not(:has(:is(a, button, input, select, textarea, label, summary):not([data-md-list-open]):hover))';
$press = '[data-md-list-row]:not([data-md-card]):active:not(:has(:is(a, button, input, select, textarea, label, summary):not([data-md-list-open]):active))';
expect($css->declarations($hover, ['@media (hover: hover)']))
->toBe(['background-color' => 'color-mix(in srgb, currentColor calc(var(--md-sys-state-hover-state-layer-opacity) * 100%), var(--md-list-row-fill, transparent))'])
->and($css->declarations($press))
->toBe(['background-color' => 'color-mix(in srgb, currentColor calc(var(--md-sys-state-pressed-state-layer-opacity) * 100%), var(--md-list-row-fill, transparent))'])
->and($css->declarations('[data-md-list-row]:not([data-md-card]):has([data-md-list-open]:focus-visible)'))
->toHaveKey('background-color', 'color-mix(in srgb, currentColor calc(var(--md-sys-state-focus-state-layer-opacity) * 100%), var(--md-list-row-fill, transparent))')
->and($css->declarations(':where([data-md-list-row])'))->toBe(['--md-list-row-fill' => 'transparent'])
->and($css->declarations("[data-md-list='segmented'] > [data-md-list-item]"))->toHaveKey('--md-list-row-fill', 'var(--md-sys-color-surface)')
->and($css->declarations('[data-md-list-item][data-md-selected]'))->toHaveKey('--md-list-row-fill', 'var(--md-sys-color-secondary-container)')
->and(File::get(ComponentStylesheet::path('table')))->toContain('--md-list-row-fill: var(--md-sys-color-secondary-container);');
// The segmented fill comes first: on the same weight, a selected tile's secondary-container wins.
expect(strpos($css->css, "[data-md-list='segmented'] > [data-md-list-item] {"))->toBeLessThan(strpos($css->css, '[data-md-list-item][data-md-selected] {'));
});
it('inks a disabled item as a whole at the disabled-content opacity', function () {
expect(ComponentStylesheet::read('list-item')->declarations("[data-md-list-item][aria-disabled='true']"))->toBe([
'pointer-events' => 'none',
'color' => 'color-mix(in srgb, var(--md-sys-color-on-surface) calc(var(--md-sys-state-disabled-content-opacity) * 100%), transparent)',
]);
});