Morph the rail's FAB, and offer a divider, no fill and a width floor
M3 asks the rail to animate its FAB into an extended FAB as it expands; the documented pattern was two FABs swapped by `display`, so the collapsed one appeared at once while the rail's width was still springing. The header now takes one <x-fab label icon> whose label springs open and shut on the rail's own spring — and names it at both widths, where the collapsed FAB had needed a tooltip to have a name at all. M3 also lists two container treatments as optional that the library had neither of: `divider` draws the vertical divider on the page's edge, which is its own answer to a page scrolling under a fixed rail, and `fill="false"` drops the container colour. Neither reaches a rail open over a scrim. And a `collapsible` rail, whose width is the visitor's choice rather than the window's, is held to the collapsed 96px below `medium`, where M3 asks for a navigation bar instead. Plan: docs/plans/material-3-alignment.md, step 21 (navigation N-22, N-23, N-24). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Opus 5
parent
1218371568
commit
7d14f2bd03
@@ -51,6 +51,22 @@ it('keeps the header and footer out of the scrolling destinations', function ()
|
||||
->toMatch('/data-navigation-rail-header.*Brand.*FAB.*data-navigation-rail-destinations.*Inbox.*data-navigation-rail-footer.*Account/s');
|
||||
});
|
||||
|
||||
it('takes M3\'s optional divider and turns the container fill off', function () {
|
||||
expect((string) $this->blade('<x-navigation-rail mode="expanded" divider :fill="false" />'))
|
||||
->toContain('data-divider')
|
||||
->toContain('data-fill="false"')
|
||||
->and((string) $this->blade('<x-navigation-rail mode="expanded" />'))
|
||||
->not->toContain('data-divider')
|
||||
->not->toContain('data-fill');
|
||||
|
||||
expect(file_get_contents(__DIR__.'/../../../resources/css/components/navigation.css'))
|
||||
// Neither reaches a rail open over a scrim, which is a surface over the page (N-22).
|
||||
->toContain('[data-navigation-rail][data-divider]:not([data-open]) > [data-navigation-rail-panel] {')
|
||||
->toContain("[data-navigation-rail][data-fill='false']:not([data-open]) > [data-navigation-rail-panel] {")
|
||||
// A collapsible rail is held to 96px where M3 asks for a navigation bar instead (N-24).
|
||||
->toMatch("/\\[data-navigation-rail='collapsible'\\] \\{\\s+width: 6rem;/");
|
||||
});
|
||||
|
||||
it('flattens a FAB nested in the rail header to elevation 0', function () {
|
||||
$html = (string) $this->blade(<<<'BLADE'
|
||||
<x-navigation-rail mode="expanded">
|
||||
@@ -58,12 +74,14 @@ it('flattens a FAB nested in the rail header to elevation 0', function () {
|
||||
</x-navigation-rail>
|
||||
BLADE);
|
||||
|
||||
// The hook the unlayered rule in navigation.css needs (N-03).
|
||||
// The hook the unlayered rules in navigation.css need (N-03).
|
||||
expect($html)->toContain('data-fab');
|
||||
|
||||
expect(file_get_contents(__DIR__.'/../../../resources/css/components/navigation.css'))
|
||||
->toContain('[data-navigation-rail-header] [data-fab],')
|
||||
->toContain('[data-navigation-rail-header] [data-fab]:hover {');
|
||||
->toContain('[data-navigation-rail-header] [data-fab]:hover {')
|
||||
// One FAB whose label springs shut, not two swapped by display (N-23).
|
||||
->toContain('[data-navigation-rail-header] [data-fab] > span {');
|
||||
});
|
||||
|
||||
it('draws a destination in both shapes, with its count on the icon and at the end', function () {
|
||||
|
||||
Reference in New Issue
Block a user