diff --git a/resources/css/components/navigation.css b/resources/css/components/navigation.css index d8374d15..2db8f579 100644 --- a/resources/css/components/navigation.css +++ b/resources/css/components/navigation.css @@ -659,11 +659,13 @@ /* "Rail transitions from collapsed to expanded should animate the FAB into and out of an extended * FAB" — so the header takes one and morphs it, rather than swapping two by * `display`, which showed the collapsed one at once while the rail's width was still springing. - * The label's width springs on the rail's own spatial spring; with the gap closed, what is left is - * 16px of padding, the 24px icon and 16px again — the 56px square a collapsed FAB is. The label + * The label's width springs on the rail's own spatial spring; with the gap closed and the extended + * FAB's own minimum width off, `aspect-ratio` squares what is left against the height its size + * already sets — 56, 80 or 96px, the three FAB sizes — so no number is repeated here. The label * stays in the accessibility tree at both widths, so the FAB keeps its name. Unlayered for the - * same reason as the rule above: `gap-2` is a utility, and a layer would lose to it. The cap is a - * transition needs a length to travel to; a rail FAB's label is a word or two. */ + * same reason as the rule above: `gap-2` and `min-w-20` are utilities, and a layer would lose to + * them. The cap is there because a transition needs a length to travel to; a rail FAB's label is a + * word or two. */ [data-navigation-rail-header] [data-fab] > span { max-width: 16rem; overflow: hidden; @@ -680,6 +682,8 @@ [data-navigation-rail-header] [data-fab] { @variant rail-collapsed { + min-width: 0; + aspect-ratio: 1; gap: 0; } } diff --git a/tests/Feature/Components/NavigationRailTest.php b/tests/Feature/Components/NavigationRailTest.php index 17df10d3..db4b3f3c 100644 --- a/tests/Feature/Components/NavigationRailTest.php +++ b/tests/Feature/Components/NavigationRailTest.php @@ -67,21 +67,16 @@ it('takes M3\'s optional divider and turns the container fill off', function () ->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' - - - - BLADE); - - // The hook the unlayered rules in navigation.css need (N-03). - expect($html)->toContain('data-fab'); - +it('flattens a FAB nested in the rail header and morphs its label', function () { + // Both rules hang off `data-fab` on 's root, and both are unlayered, because what they + // beat — the FAB's shadow, its gap, an extended FAB's minimum width — are utilities. expect(file_get_contents(__DIR__.'/../../../resources/css/components/navigation.css')) + // A nested FAB rests at elevation 0, not the 3 a standalone one has (N-03). ->toContain('[data-navigation-rail-header] [data-fab],') ->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 {'); + ->toContain('[data-navigation-rail-header] [data-fab] > span {') + ->toMatch('/@variant rail-collapsed \{\s+min-width: 0;\s+aspect-ratio: 1;\s+gap: 0;/'); }); it('draws a destination in both shapes, with its count on the icon and at the end', function () {