Sweep up navigation's last data-navigation-* references

Plan step 36 (navigation group, second batch, cleanup). Every leftover
data-navigation-*, data-tall, data-hide-on-scroll, data-hidden,
data-width, data-align, data-divider, data-fill and component-level
data-open reference outside the rewritten stylesheets and views moves
to data-md-*, in the files the two component commits left alone:
tests/Feature/Components/ScaffoldTest.php (the scaffold's own rewrite
is a later batch, but it renders the bar and the rail today and asserts
their hooks); tests/Browser/NavigationTest.php, ShowcaseTest.php and
ColourProfilesTest.php (selectors only — document-level attributes,
data-rail, data-rail-auto and data-app-shell*, keep their names).
NavigationTest.php also gets the browser tests the plan owed this
group (docs/plans/material-3-browser-tests.md § Navigation): a tall
bar's vertical layout at a width where the short bar would go
horizontal; hide-on-scroll never firing while a pinned snackbar is on
screen; a narrow rail's 80px width and centred destinations; a rail
that hides when collapsed leaving the layout and coming back only
through an application's own menu button.

resources/css/components/navigation.css and its import in tailwind.css
are deleted now that nothing imports the file any more (the previous
commit's message said this already happened there; it did not — this
is where it actually lands).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-15 00:09:44 +02:00
co-authored by Claude Sonnet 5
parent 25549374ec
commit cbd7d01c62
7 changed files with 167 additions and 903 deletions
+16 -16
View File
@@ -19,27 +19,27 @@ it('draws the adaptive rail, the bar, the content region and the snackbar host',
$html = (string) $this->blade('<x-scaffold :destinations="$destinations">The page</x-scaffold>', ['destinations' => scaffoldDestinations()]);
expect($html)
->toContain('data-navigation-rail="adaptive"')
->toContain('data-navigation-bar')
->toContain('data-md-navigation-rail="adaptive"')
->toContain('data-md-navigation-bar')
->toContain('<main id="content" tabindex="-1" wire:transition.navigate')
->toContain('max-expanded:overflow-x-clip')
->toContain('The page')
->toContain('x-data="materialSnackbar"')
->toMatch('/<a\s+href="#content"\s+data-skip-link/')
->and(strpos($html, 'data-skip-link'))->toBeLessThan(strpos($html, 'data-navigation-rail='));
->and(strpos($html, 'data-skip-link'))->toBeLessThan(strpos($html, 'data-md-navigation-rail='));
});
it('puts every destination in the rail and only those marked for the bar in the bar', function () {
$html = (string) $this->blade('<x-scaffold :destinations="$destinations" />', ['destinations' => scaffoldDestinations()]);
$rail = substr($html, strpos($html, 'data-navigation-rail='), strpos($html, 'data-app-shell-bar') - strpos($html, 'data-navigation-rail='));
$rail = substr($html, strpos($html, 'data-md-navigation-rail='), strpos($html, 'data-app-shell-bar') - strpos($html, 'data-md-navigation-rail='));
$bar = substr($html, strpos($html, 'data-app-shell-bar'));
expect(substr_count($rail, '<a data-navigation-rail-item'))->toBe(4)
->and(substr_count($bar, '<a data-navigation-bar-item'))->toBe(2)
expect(substr_count($rail, '<a data-md-navigation-rail-item'))->toBe(4)
->and(substr_count($bar, '<a data-md-navigation-bar-item'))->toBe(2)
->and($bar)->toContain('Inbox')->toContain('Sent')->not->toContain('Travel')
->and($rail)->toContain('data-navigation-rail-heading>Labels</p>')
->and(substr_count($rail, 'data-navigation-rail-section'))->toBe(1)
->and($rail)->toContain('data-md-navigation-rail-heading>Labels</p>')
->and(substr_count($rail, 'data-md-navigation-rail-section'))->toBe(1)
->and($rail)->toMatch('/href="\/receipts"(?![^>]*wire:navigate)/')
->and(substr_count($html, 'aria-current="page"'))->toBe(2);
});
@@ -99,28 +99,28 @@ it('lifts the snackbar above the bar only when there is a bar', function () {
it('passes M3\'s tall bar through, and the bottom offset grows with it', function () {
expect((string) $this->blade('<x-scaffold :destinations="$destinations" tall-bar />', ['destinations' => scaffoldDestinations()]))
->toMatch('/data-navigation-bar\s+data-tall\s/')
->toMatch('/data-md-navigation-bar\s+data-md-tall\s/')
->toContain('max-medium:[--material-bottom-bar:calc(5rem+')
->not->toContain('[--material-bottom-bar:calc(4rem+')
->and((string) $this->blade('<x-scaffold :destinations="$destinations" />', ['destinations' => scaffoldDestinations()]))
->not->toContain('data-tall')
->not->toContain('data-md-tall')
->toContain('max-medium:[--material-bottom-bar:calc(4rem+');
});
it('lets the bar leave the window while the page scrolls down', function () {
expect((string) $this->blade('<x-scaffold :destinations="$destinations" hide-bar-on-scroll />', ['destinations' => scaffoldDestinations()]))
->toContain('data-hide-on-scroll')
->toContain('data-md-hide-on-scroll')
->toContain('x-data="materialNavigationBar"')
->and((string) $this->blade('<x-scaffold :destinations="$destinations" />', ['destinations' => scaffoldDestinations()]))
->not->toContain('data-hide-on-scroll');
->not->toContain('data-md-hide-on-scroll');
});
it('exposes the rail that hides when collapsed', function () {
expect((string) $this->blade('<x-scaffold :destinations="$destinations" hide-rail-when-collapsed />', ['destinations' => scaffoldDestinations()]))
->toContain('data-hide-when-collapsed')
->toContain('data-md-hide-when-collapsed')
->toContain("materialNavigationRail('adaptive', true)")
->and((string) $this->blade('<x-scaffold :destinations="$destinations" />', ['destinations' => scaffoldDestinations()]))
->not->toContain('data-hide-when-collapsed')
->not->toContain('data-md-hide-when-collapsed')
->toContain("materialNavigationRail('adaptive', false)");
});
@@ -150,7 +150,7 @@ it('places each slot once', function () {
expect(substr_count($html, $slot))->toBe(1);
}
expect($html)->toMatch('/data-navigation-rail-header.*BRAND.*FAB.*data-navigation-rail-footer.*FOOTER.*data-app-shell-actions.*ACTIONS.*APP BAR.*<main.*PAGE/s');
expect($html)->toMatch('/data-md-navigation-rail-header.*BRAND.*FAB.*data-md-navigation-rail-footer.*FOOTER.*data-app-shell-actions.*ACTIONS.*APP BAR.*<main.*PAGE/s');
});
it('spans the window with a banner, above the rail, and renders none without the slot', function () {
@@ -163,7 +163,7 @@ it('spans the window with a banner, above the rail, and renders none without the
// Bars, then rails, then panes: the banner is outside the row the rail and the page share.
expect($html)
->toMatch('/data-app-shell-banner.*WINDOW BAR.*data-navigation-rail=.*<main/s')
->toMatch('/data-app-shell-banner.*WINDOW BAR.*data-md-navigation-rail=.*<main/s')
->and((string) $this->blade('<x-scaffold :destinations="$destinations" />', ['destinations' => scaffoldDestinations()]))
->not->toContain('data-app-shell-banner');
});