Size the loading indicator and publish the rail's value

Two gaps found rewriting the Boost skill for 2.0's plain CSS, each
closed the way M3 describes it.

`<x-loading size="96">`: M3 gives the loading indicator a responsive
size, 48dp by default and flexible from 24 to 240dp ("never exceed that
range"), with the container and the active shape in a fixed ratio. The
size had no prop, so an application wrote a width and height of its own;
`size` now takes a whole number of px in that range, written as
`--md-loading-size`, and the SVG keeps the 48:38 ratio as it scales. A
value outside the range is ignored, as `<x-icon>` and `<x-shape>` ignore
theirs, and an application's own width and height still win.

`--md-navigation-rail-value`: M3 Expressive's rail has two values,
collapsed and expanded (Compose's WideNavigationRailValue), and content
in a rail follows it. Without a hook an application copied the rail's
seven conditions — mode, `data-rail`, `data-rail-auto`, open, and the
window band — out of navigation-rail.css. The rail now publishes the
answer from the same branches that narrow it: `expanded` by default,
`collapsed` wherever it is drawn collapsed, so a style query in the
application's CSS switches at the first paint and at the same moment
as the rail's own items. A rail open over a scrim reads `expanded`, and
outside a rail the property is unset. A JS attribute would have missed
the first paint; a width container query would have lagged the collapse
animation.

Style queries on a custom property need Firefox 151, so the browser
floor moves from Firefox 147 to 151 (README, the CI note, UPGRADE's new
2.1.0 section); Chrome 125 and Safari 18.4 are unchanged.

Browser tests pin both in Chrome, Firefox and Safari: the indicator's
drawn box at 96 and 32px, and the rail's value — with a style query
acting on it — at the first paint for fixed modes, across the window
classes and the menu button for an adaptive rail, and open and closed
for a modal one. NavigationRailTest pins the value in each of the five
collapsed branches.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andreas Reinhold / reini
2026-09-16 12:06:16 +02:00
co-authored by Claude Opus 5
parent 24eb811f34
commit f2a3c4d056
13 changed files with 228 additions and 30 deletions
@@ -45,11 +45,19 @@
`footer`, pinned to the foot. Header and footer never scroll, so nothing in them is cut off by
the scroller's edge.
Anything else inside can take both shapes by matching the rail's own state directly, the same
selectors resources/css/components/navigation-rail.css uses for every branch of "collapsed"
`data-md-navigation-rail`'s value, `:not([data-md-open])`, and the window band each mode
collapses in (its header lists them). Every rule in the package that draws a collapsed shape
writes them out, and tests/Feature/Components/NavigationRailTest.php keeps each copy to the same
Anything else inside takes both shapes from the rail's value: the rail publishes M3's two
(Compose's WideNavigationRailValue) as `--md-navigation-rail-value`, `collapsed` or
`expanded`, from the first paint and in step with the rail's own items, and every descendant
inherits it, so an application's CSS asks a style query instead of repeating the conditions:
@container style(--md-navigation-rail-value: collapsed) {
.account-summary { display: none; }
}
A rail open over a scrim reads `expanded`; outside a rail the property is unset and neither
value matches. Style queries on a custom property need Chrome 111, Safari 18 or Firefox 151.
The package's own rules write the conditions out (resources/css/components/navigation-rail.css
lists them), and tests/Feature/Components/NavigationRailTest.php keeps each copy to the same
conditions. Nothing that shows while collapsed may be wider than 96px.
Props: `label` names the landmark ("Main"); `width` is the expanded width (`256px`, held