The audio player's play/pause control was the app's only mat-fab. It is now
a mat-icon-button drawn as the same 56px primary circle (icon-button
overrides: 56px state layer, 32px white icon, 50% shape, selection-colour
fill, hover scale), so the eager button chunk no longer carries the fab
directives and the theme no longer emits the fab tokens:
renderer.initialBytes 1,349,048 -> 1,329,249 bytes (-19,799: -13,799 in
button.mjs, -6,028 in the stylesheet), measured locally against the merge
base. The fab also reset the keyboard focus ring with `outline: none`; the
icon button keeps the app ring.
- tools/nx/check-material-theme-scope.mjs: `button` brings button and
icon-button; `fab` is required only while a runtime template renders
mat-fab / mat-mini-fab (matFab / matMiniFab), found through the component
templates the way check-form-field-defaults.mjs resolves them. That
resolution moves to tools/nx/component-templates.mjs, shared by both.
Templates know HTML comments only, so the scan strips just those: a `//`
in text or an attribute value no longer hides a fab on the same line.
- apps/web/src/m3-theme.scss drops `fab` from $material-components.
- apps/web-e2e: the Stalker radio test checks the control's size, shape,
fill, icon and keyboard focus ring.
- journey-baselines.json: renderer.initialBytes 1,345,807 -> 1,329,249.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Takes Angular Material off the renderer's startup path: renderer.initialBytes
1,596,201 -> 1,344,067 bytes (-252,134, 15.8%) at the branch point; merged with
master, where #1928 lands the form-field defaults per component, the branch
measures 1,345,807 (-188,797, 12.3% against master's baseline). The bundler
keeps each module in one chunk, so one eager import of any export carries the
module's whole code; each item removes the last eager importer of one Material
module.
- EPG progress and update panels: eager host + `@defer (when visible)` view
with an `@error` notice; the startup spinner is static markup copied from
mat-spinner.
- LazyMatDialog: the confirm dialog service, player service, parental lock
prompt and shell actions resolve MatDialog on first use.
- The theme emits tokens for the 21 imported components only, through a
`$material-components` list and meta.apply; tools/nx/check-material-theme-scope.mjs
(CI) keeps it in step with the imports in both directions.
- No provideAnimations(): Material 22 animates with CSS and reads
prefers-reduced-motion itself; apps/electron-backend-e2e/src/material-motion.e2e.ts
proves dialogs, selects, menus, snack-bars and tooltips animate in and out and
stop under reduced motion. Its renderer had deferred every DOM removal to the
end of the tick, so the catalog list now tracks the grid offset from scroll
events and the player settings panel decides "focus was inside" in a
microtask, both with specs that detach the view first.
- The snack-bar stays, and with it button, the icon-button chunk and the CDK
overlay (about 190 KB): root services inject it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>