Draw the scaffold without Tailwind
Plan step 36 (navigation group, third batch): <x-scaffold>'s own styling moves into resources/css/layout/scaffold.css (the content region, the bar and rail row, the banner, the actions row and its rail-collapsed column layout, --material-bottom-bar and --material-margin publishing, the skip link) alongside step 35's FAB and content-margin rules already there. Every data-app-shell* hook becomes data-md-scaffold-* (data-app-shell-bar, -actions, -banner); the skip link is data-md-skip-link; data-app-shell itself is dropped, data-md-scaffold already named the root. The actions row's rail-collapsed:flex-col is written out branch for branch as the navigation rail's own rewrite did for its internal parts: the three width-independent conditions in one :where() group, the four width-gated ones each in their own @media block. With that gone, resources/css/tailwind.css's rail-collapsed custom-variant shim (its last use) is removed; tailwind.css now carries only tokens/theme.css and tokens/utilities.css, which the showcase still needs until step 38. navigation-bar.css's hide-on-scroll rule reading --material-bottom-bar stayed unlayered only because <x-scaffold> published that variable through a Tailwind utility, which no layered rule could outrank; now scaffold.css sets it itself in material.layout, a layer navigation-bar.css's own material.components always beats, so the rule moves into the layer and the file fits one @layer material.components block like every other navigation stylesheet. navigation-bar rejoins NavigationStylesheetsTest.php's dataset and NavigationBarTest.php's own duplicate shape test is retired in favour of it. Browser tests added (docs/plans/material-3-browser-tests.md): the scaffold's FAB dropping the bar's own height once hide-bar-on-scroll slides it away, at the trailing edge in a right-to-left document, and clearing a safe area an application sets on its inline-end and bottom edges. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
20b062846d
commit
ed93222d22
@@ -1,9 +1,6 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
use NoNameWeb\LivewireMaterial\Tests\Support\ComponentStylesheet;
|
||||
use NoNameWeb\LivewireMaterial\Tests\Support\ViewClasses;
|
||||
|
||||
it('draws a navigation landmark around its items', function () {
|
||||
expect((string) $this->blade('<x-navigation-bar><x-navigation-bar-item label="Inbox" icon="inbox" link="/inbox" /></x-navigation-bar>'))
|
||||
@@ -104,41 +101,13 @@ it('hides on a scroll down and springs back on a scroll up', function () {
|
||||
->toBe(['transition' => 'translate var(--md-sys-motion-spatial-default-duration) var(--md-sys-motion-spatial-default)'])
|
||||
->and($css->declarations('[data-md-navigation-bar][data-md-hide-on-scroll][data-md-hidden]'))
|
||||
->toBe(['translate' => '0 100%'])
|
||||
->and($css->css)
|
||||
// Unlayered, or the Tailwind utility <x-scaffold> still publishes the offset with would win —
|
||||
// its own rewrite has not landed yet, so this one rule stays unlayered until it does.
|
||||
->toContain('[data-md-scaffold]:has([data-md-navigation-bar][data-md-hide-on-scroll][data-md-hidden]) {')
|
||||
->and(Str::of($css->css)->after('[data-md-scaffold]:has(')->toString())
|
||||
->not->toContain('@layer');
|
||||
// Reads --material-bottom-bar back from <x-scaffold>: layout/scaffold.css publishes it in
|
||||
// `material.layout`, which this rule's own `material.components` always outranks, so both
|
||||
// sit in a layer now (N-02's era of an unlayered Tailwind utility is gone).
|
||||
->and($css->declarations('[data-md-scaffold]:has([data-md-navigation-bar][data-md-hide-on-scroll][data-md-hidden])'))
|
||||
->toBe(['--material-bottom-bar' => 'calc(var(--material-safe-bottom, env(safe-area-inset-bottom)) + var(--material-bottom-extra, 0px))']);
|
||||
|
||||
expect(file_get_contents(__DIR__.'/../../../resources/js/navigation.js'))
|
||||
// Never out from under a snackbar, a bottom sheet or a drawer resting on its edge.
|
||||
->toContain("document.querySelectorAll('[data-md-toast-snackbar], [role=\"dialog\"]')");
|
||||
});
|
||||
|
||||
/**
|
||||
* navigation-bar.css is not in NavigationStylesheetsTest.php's dataset: it keeps one rule
|
||||
* unlayered on purpose, so its shape does not match every other stylesheet's single
|
||||
* `@layer material.components` block. These are the same checks, minus that one assumption — the
|
||||
* same reason ErrorPagesTest.php carries error-page.css's.
|
||||
*/
|
||||
it('draws navigation-bar.css shaped like every package stylesheet but its one unlayered rule', function () {
|
||||
$css = ComponentStylesheet::read('navigation-bar');
|
||||
|
||||
expect($css->css)->toStartWith('/*')
|
||||
->and($css->statements()[0] ?? null)->toBe('@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;')
|
||||
->and(array_slice($css->statements(), 1))->each->toMatch('/^@import \'\.\/[a-z-]+\.css\';$/')
|
||||
->and($css->blocks())->toContain('@layer material.components')
|
||||
->and($css->css)->not->toMatch('/@(?:tailwind|theme|utility|variant|custom-variant|apply|source|config|plugin|reference)\b|--(?:theme|spacing|alpha)\(|\btheme\(/');
|
||||
|
||||
expect(ViewClasses::violations(File::get(__DIR__.'/../../../resources/views/components/navigation-bar.blade.php')))->toBe([]);
|
||||
|
||||
$source = (string) preg_replace('~/\*.*?\*/~s', '', $css->css);
|
||||
|
||||
expect($source)->not->toMatch('/(?:^|[,{};]\s*)(?:html|body|dialog|:root)(?![\w-])(?!\[data-md-|:has\(> \[data-md-)/m');
|
||||
|
||||
$components = File::get(__DIR__.'/../../../resources/css/components.css');
|
||||
$block = substr($components, (int) strpos($components, '/* Navigation */'));
|
||||
|
||||
expect($block)->toContain("@import './components/navigation-bar.css';");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user