Files
livewire-material/UPGRADE.md
T
Andreas Reinhold / reiniandClaude Sonnet 5 ed93222d22 Draw the scaffold without Tailwind
Plan step 36 (navigation group, third batch): <x-scaffold>'s own
styling moves into resources/css/layout/scaffold.css (the content
region, the bar and rail row, the banner, the actions row and its
rail-collapsed column layout, --material-bottom-bar and
--material-margin publishing, the skip link) alongside step 35's FAB
and content-margin rules already there. Every data-app-shell* hook
becomes data-md-scaffold-* (data-app-shell-bar, -actions, -banner);
the skip link is data-md-skip-link; data-app-shell itself is dropped,
data-md-scaffold already named the root.

The actions row's rail-collapsed:flex-col is written out branch for
branch as the navigation rail's own rewrite did for its internal
parts: the three width-independent conditions in one :where() group,
the four width-gated ones each in their own @media block. With that
gone, resources/css/tailwind.css's rail-collapsed custom-variant
shim (its last use) is removed; tailwind.css now carries only
tokens/theme.css and tokens/utilities.css, which the showcase still
needs until step 38.

navigation-bar.css's hide-on-scroll rule reading --material-bottom-bar
stayed unlayered only because <x-scaffold> published that variable
through a Tailwind utility, which no layered rule could outrank; now
scaffold.css sets it itself in material.layout, a layer
navigation-bar.css's own material.components always beats, so the
rule moves into the layer and the file fits one
@layer material.components block like every other navigation
stylesheet. navigation-bar rejoins NavigationStylesheetsTest.php's
dataset and NavigationBarTest.php's own duplicate shape test is
retired in favour of it.

Browser tests added (docs/plans/material-3-browser-tests.md): the
scaffold's FAB dropping the bar's own height once hide-bar-on-scroll
slides it away, at the trailing edge in a right-to-left document, and
clearing a safe area an application sets on its inline-end and bottom
edges.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-15 00:37:22 +02:00

9.6 KiB

Upgrading

From 1.x to 2.0.0

2.0.0 aligns the library with Material Design 3 Expressive as Google documents it (m3.material.io, checked page by page; the audits are in docs/audits/m3-alignment/). Most of the change is inside the components. What reaches an application is below, in the order to do it.

1. Breakpoints are M3's window size classes

Tailwind's sm:, md:, lg:, xl: and 2xl: no longer compile. The variants are medium: (600px), expanded: (840px), large: (1200px) and extra-large: (1600px), plus max-medium: and friends for "below"; compact is everything below medium. Replace every prefix in the application's views:

Was Becomes
sm: / max-sm: (640) medium: / max-medium: (600)
md: / max-md: (768) medium: or expanded: — choose by what the layout means
lg: / max-lg: (1024) expanded: / max-expanded: (840)
xl: / max-xl: (1280) large: / max-large: (1200)
2xl: (1536) extra-large: (1600)

Scripts read the same numbers from resources/js/breakpoints.js (from('expanded'), upTo('medium')). DesignGuard reports every leftover prefix with its replacement.

2. Only M3's scales compile

Tailwind's default radius, shadow, text-size, weight, leading, tracking and easing utilities are cleared like its palette was:

Was Becomes
rounded-smrounded-4xl rounded-corner-xsrounded-corner-xxl (rounded-corner-full, rounded-corner-none)
shadow-smshadow-2xl shadow-elevation-1shadow-elevation-5
text-xstext-9xl, leading-*, tracking-*, font-mediumfont-black one type-* style (type-body-md, type-emphasized-title-md …)
ease-in, ease-out, ease-in-out, duration-300 ease-spatial-* / ease-effects-* with duration-(--md-sys-motion-…-duration)

The 4px spacing scale is unchanged. DesignGuard names each one with its replacement.

3. Regenerate the colour scheme

php artisan material:scheme "#4f46e5" --variant=tonal-spot   # the command in the file's header
  • success, warning and info are now built on the 2025 colour spec with the contrast level, like error; their values change. --harmonize blends them toward the seed (off by default).
  • The stylesheet gains medium and high contrast blocks, and material-scheme.json gains a contrast key; light/dark at the top level are still the standard scheme, so the mail theme needs nothing. --contrast must now be below 0.5; medium (0.5) and high (1.0) are generated alongside.
  • Config: theme.contrast (default system | standard | medium | high, storage_key) and motion.scheme (expressive | standard). $store.theme gains contrast, resolvedContrast and setContrast(); <x-theme-toggle mode="contrast"> is a row of three.

4. Inks are roles, not opacities

text-meta, text-quiet, border-chrome and border-divider keep their names but now resolve to on-surface-variant, outline, outline-variant and outline-variant. Where the old translucent grey was intended, nothing to do; where a template relied on the opacity to blend over a colour, use the role directly.

5. Changed defaults and props

  • <x-toast> no longer draws a state icon; type only picks the announcement role (alert for error and warning, status otherwise). An actioned snackbar stays until acted on; Escape dismisses a focused one.
  • <x-fab> has no disabled prop: M3 says to remove a FAB whose action is unavailable, so hide it instead (a form-submit FAB uses wire:loading.attr="disabled").
  • <x-alert> is role="status" for every colour; pass assertive where the notice answers something the person just did.
  • <x-button size="xs"> and <x-group size="xs"> are 8px wider; a <x-button-group> no longer wraps; connected xs/sm segments have a 48px minimum width.
  • <x-menu-item> rows are 48px with 16px sides; a selected item draws a trailing check unless it has icon-right; a long menu scrolls.
  • <x-drawer> renders a close button by default (:with-close-button="false" to drop it, ignored on a standard sheet or when Escape and the scrim are off) and left-aligns its actions in a 72px row. <x-drawer pane> is removed; use <x-list-detail> for the second pane of a list-detail layout.
  • <x-bottom-sheet> opens at 50dvh (was 90dvh); any height is capped at calc(100dvh - 72px).
  • <x-carousel> padding defaults to 16; layout="full-screen" scrolls vertically with edge-to-edge items; items, not the row, are the tab stops.
  • <x-list dividers> draws a 16px-inset rule; <x-list selectable> or selection="single|multi" makes it a listbox of options with aria-selected.
  • <x-card> changes elevation on hover instead of its corner; data-md-card carries the variant.
  • <x-modal> pins its header and actions and scrolls only the body; a box-class that set overflow no longer applies.
  • <x-table> rows are 52px and the automatic fine-pointer density is gone: pass dense for 36px rows (size="xs" dense is 24px).
  • A field in error draws a trailing error icon unless it already trails something; a read-only field no longer draws a dashed outline.
  • The time picker's AM/PM buttons are radios (aria-checked); the password reveal no longer sets aria-pressed.
  • <x-slider size="md"> grows from 44 to 52px and every value indicator from 32 to 44px tall.
  • <x-theme-toggle mode="picker"|"contrast"> is a connected group over native radios: the data-theme-option hooks are gone; target input[name="material-theme"][value="…"].
  • <x-tab> panels render id, aria-labelledby and display: none from the server.
  • <x-section-nav> with five or more sections is a scrollable tab bar, not a grid. The tab bar is 10px taller; the focus ring sits outside.
  • The navigation bar's horizontal label is label-md; place="bottom" toolbars sit above --material-bottom-bar; a standard toolbar's icon buttons are primary.
  • The centred app bar headline is a grid column; the search variant bounds its own width, so drop hand-written max-w-* wrappers.
  • <x-app-shell> is renamed <x-scaffold>, with no alias; it is a column with a nested row and gains banner and fab slots. <x-navigation-rail>'s header slot takes one <x-fab label icon> that morphs (replace the two-FAB rail-collapsed: swap); new divider and fill props. data-app-shell, data-app-shell-bar, data-app-shell-actions and data-app-shell-banner are data-md-scaffold, data-md-scaffold-bar, data-md-scaffold-actions and data-md-scaffold-banner; the skip link is data-md-skip-link.
  • <x-icon optical="20"> selects the optical-size-20 cut; the components pass it for their own small icons, applications pass it for icons drawn at 20px or less.
  • A text field stops at 40rem wide from medium:, as M3 bounds fields on wider windows; a max-w-* class on the field beats it, and full removes it.
  • Every <x-modal> draws a rule under its header and over its actions while its body scrolls, and neither when the body fits. separator now means "always draw both rules" and no longer renders two <x-divider> elements; the spacing between header, body and actions moved to M3's split gaps, so a dialog that fits is a few pixels shorter.
  • A snackbar with a description is 68px tall, and below medium: a two-line snackbar with an action puts the action under the text. Alt+G moves focus to an actioned snackbar.
  • <x-bottom-sheet>'s drag now follows the pointer and settles on the nearest preset height when heights or snap is set; without stops it behaves as before.
  • A chip set with scroll shows a scroll button over each overflowing edge on fine pointers.

6. New in 2.0.0

Nothing to migrate, but worth knowing: submenus (<x-menu-item submenu>), a filtering menu (<x-menu filter>), a menu that opens as a bottom sheet on compact windows (<x-menu sheet-at-compact>), gap-grouped menu items (<x-menu-group gap>), square button groups (shape="square"), managed selection on connected groups (selection="single|multi" required), FAB collapse on scroll (<x-fab collapse-on-scroll>), the tall navigation bar and hide-on-scroll (tall, hide-on-scroll; tall-bar, hide-bar-on-scroll on the shell), the narrow, centred and hide-when-collapsed rail (width="narrow", align="center", hide-when-collapsed), a docked toolbar with a FAB and a rounded large-screen form (rounded), app bar actions that overflow into a menu (:actions="[…]"), the list item's video slot, the card's dragged state, the standard side sheet (<x-drawer standard>), bottom sheet preset heights, the multi-aspect carousel (layout="multi-aspect"), the divider with a subheader (<x-divider text>), the character counter (counter), the vertical slider (orientation="vertical"), the full-screen range date picker on compact windows, search's icon entry point and suggestions (trigger="icon", suggestions slot), the contrast toggle (<x-theme-toggle mode="contrast">) and the Standard motion scheme.

7. Tests and guards

Add DesignGuard's new checks to the application's design test (forbidOpacityInk() and forbidAbsolutes() are opt-in). Browser tests that assert widths switch at 640/1024/1280 now switch at 600/840/1200; tests that read role="alert" on an alert, aria-pressed on the time picker's period buttons or data-theme-option need the new hooks above.

8. For AI agents

php artisan boost:update --discover picks up the new material-3 guideline and the material-3-design skill, which state M3's rules and tables beside the library's utilities.