Cut duplicated and speculative code across the package

An over-engineering audit of the whole tree, applied in five reviewed
batches. Behaviour stays the same except where UPGRADE.md says otherwise.

PHP: the showcase and error-page stylesheets are prebuilt into
resources/dist by bin/stylesheets.mjs, through Vite's own postcss-import
(first occurrence kept, the order an application's build gives), instead
of Stylesheets::bundle() inlining imports on every request; only the
import walk DesignGuard needs stays. SchemeStylesheet::withProfiles()
replaces three copies of the scheme-plus-profiles loop, material:scheme
leaves spec and contrast checks to the node script that already made
them, and the error page's scheme cache, the hashed view namespace, the
translations path with no lang/ folder and DesignGuard's 1.x-name hints
are gone.

JS: the androidx shape port progress.js and both bin scripts each carried
lives once in resources/js/shapes.js (the generated SVGs are unchanged);
util.js holds ringIndex(), ms(), reopenGuard() and remember(), which
were written out several times; listeners are released through
AbortController; tooltip.js's hoverPopover() serves the rich tooltip too.

CSS: every rule for an element inside the navigation rail queries
`--md-navigation-rail-value` instead of repeating the seven collapsed
conditions under five media branches; badge, alert, progress, slider and
button read one non-inheriting colour-role table (components/color.css);
the dialog chrome, the submenu's popover chrome, the chip's state layer
and touch target, and the visually-hidden inputs use the shared rules
they copied; foundation/tokens.css is folded into foundation.css.

Views: Support\Field and Support\Link replace the error-key, bound-value
and link-attribute blocks copied into the fields and link components;
the timepicker period group, the menu filter and the showcase head are
partials; the datepicker's steppers and entry fields are loops; component
docblocks no longer restate SKILL.md.

Tests and tooling: one dataset-driven ComponentStylesheetsTest replaces
four per-group files, DesignGuardTest and the layout-component tests use
datasets, browser tests share one ready() helper, CSS parsing lives in
ComponentStylesheet alone. docs/audits and the finding IDs citing it are
removed, as are pestphp/pest-plugin-laravel, the unused composer scripts
and check:font; the lint job runs in the feature job, which now installs
node packages so the prebuilt-stylesheet staleness test runs in CI.

Feature suite 1177 passed, Chrome browser suite 299 passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andreas Reinhold / reini
2026-09-17 19:29:21 +02:00
co-authored by Claude Opus 5
parent 471d927e64
commit 247c596c3a
233 changed files with 16635 additions and 10579 deletions
+60 -103
View File
@@ -104,8 +104,7 @@ function collapseProbe()
</html>
BLADE));
return visit('/collapse-probe')->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined' && typeof window.Livewire !== 'undefined'");
return ready(visit('/collapse-probe'));
}
function overlayProbe()
@@ -127,14 +126,12 @@ function overlayProbe()
</html>
BLADE));
return visit('/overlay-probe')->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined' && typeof window.Livewire !== 'undefined'");
return ready(visit('/overlay-probe'));
}
function containment()
{
return visit('/material/containment')->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined' && typeof window.Livewire !== 'undefined'");
return ready(visit('/material/containment'));
}
it('writes back what closed means: false for a flag, null for an id', function () {
@@ -265,8 +262,7 @@ function nestedDialogProbe()
</html>
BLADE));
return visit('/nested-dialog-probe')->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined' && typeof window.Livewire !== 'undefined'");
return ready(visit('/nested-dialog-probe'));
}
it('marks a scrolling dialog\'s divider at the edge with more content, and a nested dialog keeps its own marks', function () {
@@ -356,8 +352,7 @@ it('opens a dialog with no fade under reduced motion, but a real one without it'
// With reduced motion (the plugin's own emulation, `visit(..., ['reducedMotion' => 'reduce'])`):
// tokens/motion.css takes the same spring's duration to zero, so there is no transition to run,
// and the dialog is at its final opacity at once rather than mid-fade.
$reduced = visit('/material/containment', ['reducedMotion' => 'reduce'])->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined' && typeof window.Livewire !== 'undefined'")
$reduced = ready(visit('/material/containment', ['reducedMotion' => 'reduce']))
->assertScript("window.matchMedia('(prefers-reduced-motion: reduce)').matches");
$reduced->click('#containment button:has-text("Basic dialog")');
@@ -403,8 +398,7 @@ function textOnlyDialogProbe()
</html>
BLADE));
return visit('/text-only-dialog-probe')->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined' && typeof window.Livewire !== 'undefined'");
return ready(visit('/text-only-dialog-probe'));
}
it('gives the scrolling body an inset focus ring when a text-only dialog opens from the keyboard', function () {
@@ -634,8 +628,7 @@ function layersProbe(): mixed
</html>
BLADE));
return visit('/layers-probe')->resize(1000, 800)->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined'");
return ready(visit('/layers-probe')->resize(1000, 800), livewire: false);
}
function sheetOpen(string $id): string
@@ -963,12 +956,39 @@ it('binds a collapse to an Alpine property both ways', function () {
->assertScript("{$collapse}.open === false");
});
it('fades the side sheet\'s scrim out on close, rather than making it vanish', function () {
$sheet = "document.querySelector('#containment aside[role=\"dialog\"]')";
$scrim = "{$sheet}.parentElement.querySelector(':scope > [data-md-drawer-scrim]')";
/**
* The side sheet and the bottom sheet close the same way — a fade on the scrim, a slide on the
* sheet itself — differing only in the selector each renders under, the click that opens it, the
* scrim's own hook attribute, the dimension it slides across, the `translate` component that
* carries the offset (a single value for the side sheet's horizontal slide, the second of a
* `translate: x y` pair for the bottom sheet's vertical one) and whether that offset is read
* signed: the side sheet's can slide either way (a right-to-left page), so its mid-slide sample
* takes `Math.abs()`; the bottom sheet only ever slides down, so its own stays signed.
*/
dataset('containment sheets', [
'side sheet' => [
"document.querySelector('#containment aside[role=\"dialog\"]')",
'#containment button:has-text("Side sheet")',
'data-md-drawer-scrim',
'width',
'',
true,
],
'bottom sheet' => [
"document.querySelector('#containment section[role=\"dialog\"]')",
'#containment button:has(> span:text-is("Bottom sheet"))',
'data-md-bottom-sheet-scrim',
'height',
".split(' ')[1]",
false,
],
]);
it('fades the sheet\'s scrim out on close, rather than making it vanish', function (string $sheet, string $trigger, string $scrimAttr) {
$scrim = "{$sheet}.parentElement.querySelector(':scope > [{$scrimAttr}]')";
$page = containment()
->click('#containment button:has-text("Side sheet")')
->click($trigger)
->assertScript("getComputedStyle({$sheet}).display !== 'none'")
->assertScript("getComputedStyle({$scrim}).opacity === '1'");
@@ -994,57 +1014,31 @@ it('fades the side sheet\'s scrim out on close, rather than making it vanish', f
expect($midFade)->toBeTrue();
$page->assertScript("getComputedStyle({$scrim}).display === 'none'");
});
})->with('containment sheets');
it('fades the bottom sheet\'s scrim out on close, rather than making it vanish', function () {
$sheet = "document.querySelector('#containment section[role=\"dialog\"]')";
$scrim = "{$sheet}.parentElement.querySelector(':scope > [data-md-bottom-sheet-scrim]')";
it('slides the sheet out on close, rather than making it vanish', function (string $sheet, string $trigger, string $scrimAttr, string $dimension, string $axis, bool $absolute) {
$scrim = "{$sheet}.parentElement.querySelector(':scope > [{$scrimAttr}]')";
$offset = "(parseFloat(getComputedStyle({$sheet}).translate{$axis}) || 0)";
$sample = $absolute ? "Math.abs(parseFloat(style.translate{$axis}) || 0)" : "(parseFloat(style.translate{$axis}) || 0)";
$page = containment()
->click('#containment button:has(> span:text-is("Bottom sheet"))')
->click($trigger)
->assertScript("getComputedStyle({$sheet}).display !== 'none'")
->assertScript("getComputedStyle({$scrim}).opacity === '1'");
$midFade = $page->script(<<<JS
(async () => {
{$scrim}.click()
for (let i = 0; i < 60; i++) {
const opacity = parseFloat(getComputedStyle({$scrim}).opacity)
if (opacity > 0.02 && opacity < 0.98) return true
await new Promise((resolve) => setTimeout(resolve, 5))
}
return false
})()
JS);
expect($midFade)->toBeTrue();
$page->assertScript("getComputedStyle({$scrim}).display === 'none'");
});
it('slides the side sheet out on close, rather than making it vanish', function () {
$sheet = "document.querySelector('#containment aside[role=\"dialog\"]')";
$scrim = "{$sheet}.parentElement.querySelector(':scope > [data-md-drawer-scrim]')";
$page = containment()
->click('#containment button:has-text("Side sheet")')
->assertScript("getComputedStyle({$sheet}).display !== 'none'")
->assertScript("Math.abs(parseFloat(getComputedStyle({$sheet}).translate)) < 0.5");
->assertScript("Math.abs({$offset}) < 0.5");
// Sampled in the page, in the same round trip as the close, as the scrim's fade is above: the
// sheet must be caught still displayed and part of the way to its closed offset (one sheet
// width past its edge), not gone at once — which is what Firefox showed while the exit leaned
// on `allow-discrete` holding `display`.
// sheet must be caught still displayed and part of the way to its closed offset (one sheet's
// own size past its edge), not gone at once — which is what Firefox showed while the exit
// leaned on `allow-discrete` holding `display`.
$midSlide = $page->script(<<<JS
(async () => {
const width = {$sheet}.getBoundingClientRect().width
const size = {$sheet}.getBoundingClientRect().{$dimension}
{$scrim}.click()
for (let i = 0; i < 60; i++) {
const style = getComputedStyle({$sheet})
const offset = Math.abs(parseFloat(style.translate) || 0)
if (style.display !== 'none' && offset > 1 && offset < width - 1) return true
const offset = {$sample}
if (style.display !== 'none' && offset > 1 && offset < size - 1) return true
await new Promise((resolve) => setTimeout(resolve, 5))
}
return false
@@ -1054,36 +1048,7 @@ it('slides the side sheet out on close, rather than making it vanish', function
expect($midSlide)->toBeTrue();
$page->assertScript("getComputedStyle({$sheet}).display === 'none'");
});
it('slides the bottom sheet down on close, rather than making it vanish', function () {
$sheet = "document.querySelector('#containment section[role=\"dialog\"]')";
$scrim = "{$sheet}.parentElement.querySelector(':scope > [data-md-bottom-sheet-scrim]')";
$offset = "(parseFloat(getComputedStyle({$sheet}).translate.split(' ')[1]) || 0)";
$page = containment()
->click('#containment button:has(> span:text-is("Bottom sheet"))')
->assertScript("getComputedStyle({$sheet}).display !== 'none'")
->assertScript("Math.abs({$offset}) < 0.5");
$midSlide = $page->script(<<<JS
(async () => {
const height = {$sheet}.getBoundingClientRect().height
{$scrim}.click()
for (let i = 0; i < 60; i++) {
const offset = {$offset}
if (getComputedStyle({$sheet}).display !== 'none' && offset > 1 && offset < height - 1) return true
await new Promise((resolve) => setTimeout(resolve, 5))
}
return false
})()
JS);
expect($midSlide)->toBeTrue();
$page->assertScript("getComputedStyle({$sheet}).display === 'none'");
});
})->with('containment sheets');
it('slides the side sheet in from its own edge in a right-to-left page', function () {
Route::middleware('web')->get('/drawer-rtl-probe', fn () => Blade::render(<<<'BLADE'
@@ -1104,8 +1069,7 @@ it('slides the side sheet in from its own edge in a right-to-left page', functio
</html>
BLADE));
$page = visit('/drawer-rtl-probe')->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined'");
$page = ready(visit('/drawer-rtl-probe'), livewire: false);
$sheet = "document.querySelector('aside[data-md-side]')";
@@ -1171,8 +1135,7 @@ it('keeps a basic dialog\'s own title and padding when it is nested inside a ful
</html>
BLADE));
$page = visit('/nested-fullscreen-dialog-probe')->resize(400, 800)->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined' && typeof window.Livewire !== 'undefined'");
$page = ready(visit('/nested-fullscreen-dialog-probe')->resize(400, 800));
$page->click('button:has-text("Open settings")');
@@ -1234,8 +1197,7 @@ it('keeps a selected segmented row\'s fill under the hover and focus tint', func
</html>
BLADE));
$page = visit('/segmented-selected-row-probe')->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined'");
$page = ready(visit('/segmented-selected-row-probe'), livewire: false);
$selected = "document.querySelector('[data-md-selected]')";
$plain = "document.querySelector('[data-md-list-item]:not([data-md-selected])')";
@@ -1301,8 +1263,7 @@ it('fills a selected row written by hand in secondary-container in both themes,
</html>
BLADE));
$page = visit('/hand-made-selected-row-probe')->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined'");
$page = ready(visit('/hand-made-selected-row-probe'), livewire: false);
$swatch = settledPaint("document.getElementById('swatch')");
$row = settledPaint("document.getElementById('selected-row')");
@@ -1376,8 +1337,7 @@ function collapseMotionProbe(string $durations = ''): mixed
</html>
BLADE));
$page = visit('/collapse-motion-probe')->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined'");
$page = ready(visit('/collapse-motion-probe'), livewire: false);
if ($durations !== '') {
$page->script("document.head.insertAdjacentHTML('beforeend', '<style>:root { --md-sys-motion-spatial-fast-duration: {$durations}; }</style>')");
@@ -1658,8 +1618,7 @@ it('shows no tooltip on the control a sheet or a dialog focuses as it opens, but
// A phone, where the sheet is modal and traps the focus, which it moves to its ✕ on open: here
// on a page loaded with the sheet open, as a link to a session opens it.
$page = visit('/opened-layers-probe?workout=7', ['viewport' => ['width' => 393, 'height' => 800]])->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined'")
$page = ready(visit('/opened-layers-probe?workout=7', ['viewport' => ['width' => 393, 'height' => 800]]), livewire: false)
->assertScript("document.activeElement.matches('{$sheet} button[aria-label=\"Close\"]')")
->wait(0.3)
->assertScript('! '.closeTooltipOpen($sheet));
@@ -1670,8 +1629,7 @@ it('shows no tooltip on the control a sheet or a dialog focuses as it opens, but
->assertScript(closeTooltipOpen($sheet));
// A full-screen dialog opened from the keyboard moves the focus to its bar's ✕ in showModal().
$page = visit('/opened-layers-probe', ['viewport' => ['width' => 393, 'height' => 800]])->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Livewire !== 'undefined'");
$page = ready(visit('/opened-layers-probe', ['viewport' => ['width' => 393, 'height' => 800]]), alpine: false);
$page->keys('#open-setback', 'Enter')
->assertScript("document.querySelector('{$dialog}').open && document.activeElement.matches('{$dialog} button[aria-label=\"Close\"]')")
@@ -1683,8 +1641,7 @@ it('shows no tooltip on the control a sheet or a dialog focuses as it opens, but
->assertScript(closeTooltipOpen($dialog));
// A rich tooltip's trigger as the first control of a dialog opened from the keyboard.
$page = visit('/opened-layers-probe', ['viewport' => ['width' => 393, 'height' => 800]])->waitForEvent('networkidle')
->assertScript("document.readyState === 'complete' && typeof window.Livewire !== 'undefined'");
$page = ready(visit('/opened-layers-probe', ['viewport' => ['width' => 393, 'height' => 800]]), alpine: false);
$page->keys('#open-about', 'Enter')
->assertScript("document.activeElement.id === 'about-help'")