Write the showcase examples without showcase-only hooks

Plan step 38 review: the component sections' code samples, which an
application copies, carried 60 data-md-showcase-* hooks that only
showcase.css draws (a sized loading indicator, the plain badge's own
colours, a bordered bar frame, the navigation demos' frames, a table's
scroll wrapper...), so a copied sample did nothing in the application.
They now write what an application has: <x-surface outlined corner>
for a frame and a line, <x-row> for the FAB menu's corner, and an
inline style from the tokens for a size, a scroll box or a colour,
as the Containment batch already did. The side sheet demo takes
align="stretch", which holds in both of <x-row stack-below>'s modes,
instead of a hook that undid align="start" once stacked. The menu
icon colours go through icon-class with two unlayered application-like
classes, which the sample's comment names, and the fields' and date
picker's widths are inline styles now that style reaches their roots.
The radio hint said "from sm"; it is medium.

showcase.css keeps only the frame and the foundation specimens; its
header describes the file instead of the batches that wrote it. The
tests reject a showcase hook or a class outside md-* and the named
application classes in any example, a showcase.css selector outside
its own hooks, and a hook no showcase view renders.

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-15 06:21:18 +02:00
co-authored by Claude Opus 5
parent cd47aa4b0f
commit ebdcdb82b5
15 changed files with 152 additions and 374 deletions
+13 -1
View File
@@ -132,7 +132,19 @@ it('writes every example as an application writes it', function () {
foreach ($examples as [$file, $code]) {
// The example component rewrites unprefixed tags to a configured prefix; a namespaced tag
// would show an application a form it does not write, and escape that rewrite.
expect($code)->not->toContain('x-livewire-material::', "{$file} writes a namespaced tag in an example");
expect(str_contains($code, 'x-livewire-material::'))->toBeFalse("{$file} writes a namespaced tag in an example");
// Nor a hook only showcase.css draws, which would do nothing in the application's page.
expect(str_contains($code, 'data-md-showcase'))->toBeFalse("{$file} writes a showcase hook in an example");
// A class is a text or interaction class, or one of the application's own that
// showcase.css stands in for, each named in its header.
preg_match_all('/class="([^"]*)"/', $code, $classes);
foreach (preg_split('/\s+/', implode(' ', $classes[1]), -1, PREG_SPLIT_NO_EMPTY) as $class) {
expect(str_starts_with($class, 'md-') || in_array($class, ['showcase-w-narrow', 'showcase-ink-tertiary', 'showcase-ink-secondary'], true))
->toBeTrue("{$file} writes the class `{$class}` in an example");
}
}
});
+21 -4
View File
@@ -698,15 +698,32 @@ it('shapes showcase.css like a package stylesheet, with its documented unlayered
->and($item['statement'])->toMatch('/^@import ([\'"])\.{1,2}\/[\w.\/-]+\.css\1;$/', "`{$item['statement']}` is not a plain import");
}
// showcase.css has no imports of its own yet (its header says why); the day it needs one, this
// showcase.css has no imports of its own (its header says why); the day it needs one, this
// still holds because it is a plain @import assertion above, not a fixed empty list here.
expect($unlayered)->toBe([
// Deliberately unlayered — see the file's header and .showcase-w-narrow's own comment.
'.showcase-w-sm' => true,
'.showcase-w-xs' => true,
// Deliberately unlayered, as an application's own classes are — see the file's header.
'.showcase-w-narrow' => true,
'.showcase-ink-tertiary' => true,
'.showcase-ink-secondary' => true,
]);
// Bundled with all.css on every showcase page, so it styles its own hooks and classes only,
// and each of those is still drawn by some showcase view.
preg_match_all('/([^{};]+)\{/', preg_replace('/@(?:layer|media)\b[^{]*\{/', '', stylesheetWithoutComments($css)), $preludes);
$views = collect(File::allFiles(__DIR__.'/../../resources/views/showcase'))->map(fn ($file): string => $file->getContents())->implode("\n");
foreach ($preludes[1] as $prelude) {
foreach (array_map('trim', explode(',', $prelude)) as $selector) {
expect($selector)->toMatch('/^(?:\[data-md-showcase[\w-]*[\]=]|\.showcase-[\w-]+)/', "showcase.css selects `{$selector}`, outside the showcase's own hooks");
}
}
preg_match_all('/data-md-showcase(?:-\w+)*|\.showcase(?:-\w+)+/', stylesheetWithoutComments($css), $hooks);
foreach (array_unique($hooks[0]) as $hook) {
expect(str_contains($views, ltrim($hook, '.')))->toBeTrue("showcase.css draws `{$hook}`, which no showcase view renders");
}
preg_match_all('/@media\b([^{]*)\{/', stylesheetWithoutComments($css), $matches);
foreach ($matches[1] as $query) {