Files
livewire-material/resources/boost/skills/material-3-design/SKILL.md
T
Andreas Reinhold / reiniandClaude Sonnet 5 9dd527f303 Rewrite the drawer (side sheet) without Tailwind, remove pane
Plan step 36 (containment group): <x-drawer>'s class lists move into
resources/css/components/drawer.css, keyed on data-md-drawer (with
data-md-open, data-md-standard) and data-md-drawer-scrim/-sheet
(data-md-side)/-head/-head-row/-heading/-title/-subtitle/-close/-body/
-actions. The modal sheet slides in on the emphasized-decelerate
easing and out on emphasized-accelerate (an asymmetric CSS transition
expressed by giving the open-state selector its own
transition-duration/-timing-function, which the "after-change style"
rule picks up); the sheet stays x-show-driven, with @starting-style +
transition-behavior: allow-discrete taking the place of x-transition's
enter/leave classes, matching resources/css/components/search.css's
already-rewritten scrim/view. A standard sheet drops the scrim and
trap from 840px and only fades in place (an in-flow box does not
travel); data-md-drawer-collapsed (from the view's `wide` Alpine
state) takes it out of the layout while closed there.

<x-drawer pane> is removed: step 35's <x-list-detail> is M3's form of
that job (the plan's decision, docs/plans/material-3-alignment.md
"Decisions"). Removed the prop, its CSS classes and its tests
(OverlayTest's two pane-only tests deleted, the others' pane cases
dropped); pointed each mention at <x-list-detail> in the material-3
guideline, the material-3-design and livewire-material-development
skills, and added a line to UPGRADE.md's 2.0.0 notes. No other living
file named `<x-drawer pane>` (grepped views, tests, README, boost,
workbench excluding build output); docs/plans and docs/audits keep
their history unchanged.

Imported from the Containment block of components.css, importing
button.css and divider.css for what the view renders.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 21:07:04 +02:00

28 KiB
Raw Blame History

name, description
name description
material-3-design Material 3 Expressive's design system as Livewire Material implements it — colour roles and surface containers, elevation, shape, type, motion, states and targets, window size classes, spacing, icons, accessibility — each M3 name beside the utility that draws it and Google's source page, for deciding how a screen should look and behave before writing it.

Material 3 design

When to use this skill

Use this skill when deciding how a screen, panel or control should look or behave — which colour, container, corner, type style, motion, breakpoint or spacing — in an application that requires nonameweb/livewire-material, and when reviewing a view against Material 3. The props and slots of each component are in the livewire-material-development skill; this one is the design language they implement. The rules an agent must always follow are in the material-3 guideline; the tables here are what those rules compress.

Every table pairs the M3 name with the library's utility or attribute. The tokens are CSS variables (--md-sys-color-*, --md-sys-typescale-*, --md-sys-shape-*, --md-sys-elevation-*, --md-sys-motion-*, --md-sys-state-*, --md-sys-measurement-*, --md-ref-typeface-*) and the utilities read them, so a template names a utility and never a variable or a value.

Colour

A colour scheme is generated from one seed by Google's colour science (php artisan material:scheme); every role below is a slot in that scheme, light and dark, at three contrast levels. A template names a role and nothing else — never a hex, a palette tone, an arbitrary value or an opacity — because only a role follows the theme, the contrast level and a colour profile.

Roles

Role Purpose Its on- pair Utility
primary High-emphasis fills, text and icons: the key action on a screen on-primary bg-primary text-on-primary, text-primary
primary-container A standout fill for key components (FAB, an emphasised panel) on-primary-container bg-primary-container text-on-primary-container
primary-dim A darker primary for a pressed or contrasting fill (2025 spec) on-primary bg-primary-dim
secondary Less prominent fills, text and icons on-secondary bg-secondary text-on-secondary
secondary-container The recessive fill: tonal buttons, selected navigation, selected chips on-secondary-container bg-secondary-container text-on-secondary-container
tertiary A complementary accent, used sparingly for contrast on-tertiary bg-tertiary text-on-tertiary
tertiary-container The complementary fill on-tertiary-container bg-tertiary-container text-on-tertiary-container
error Urgency and errors; static, does not follow dynamic colour on-error text-error, bg-error text-on-error
error-container An error panel on-error-container bg-error-container text-on-error-container
success, warning, info This library's custom state colours, built like error on the 2025 spec, with -container and on- pairs on-success … text-success, bg-warning-container text-on-warning-container
surface The page background on-surface bg-surface text-on-surface
on-surface-variant Lower-emphasis text and icons on any surface text-on-surface-variant, text-body, text-meta
outline A boundary that must be read: a text field, a target's edge (3:1 against surface) border-outline, text-outline, text-quiet
outline-variant Decorative lines: dividers, card edges border-outline-variant, border-divider, border-structure, border-chrome, divide-divider
inverse-surface A surface that contrasts with its surroundings (the snackbar) inverse-on-surface bg-inverse-surface text-inverse-on-surface
inverse-primary An action on an inverse surface (the snackbar's action) text-inverse-primary
scrim Behind a modal, at 32% bg-scrim/32
shadow The shadow colour, inside shadow-elevation-*
surface-dim, surface-bright Add-on surfaces that keep their relative brightness in both themes on-surface bg-surface-dim, bg-surface-bright
primary-fixed, primary-fixed-dim, on-primary-fixed, on-primary-fixed-variant (and secondary, tertiary) Add-on roles with the same tone in light and dark; for a colour that must not change with the theme; never where contrast matters bg-primary-fixed text-on-primary-fixed

Pairing: a role's on- pair is the only combination whose contrast is guaranteed at every contrast level. bg-primary text-on-primary and bg-secondary-container text-on-secondary-container are right; bg-primary-container text-on-surface or bg-secondary-container text-primary are not, and break as the contrast level rises. Google: "Pair and layer color roles only as intended … Don't mix roles improperly."

Surface containers

A hierarchy of emphasis, not of height: the tone separates panels before any shadow does, and a region keeps its role at every breakpoint (body always surface, navigation always surface-container).

Role Use Utility
surface The page bg-surface
surface-container-lowest The most recessed panel; an elevated card's body in dark themes bg-surface-container-lowest
surface-container-low An elevated card, a modal bottom or side sheet, the full-screen search view bg-surface-container-low
surface-container Navigation bar and rail, docked and floating toolbars, menus, the segmented list bg-surface-container
surface-container-high Dialogs, the search bar, date and time pickers, a rich tooltip bg-surface-container-high
surface-container-highest A filled card, a filled text field, a filled chip's selected state bg-surface-container-highest

Emphasis and lines

  • Default ink is on-surface; lower emphasis is on-surface-variant; decoration is outline. Emphasis is never an opacity: M3 reserves 38% (/38) for disabled content and 12% (/12) for a disabled container.
  • outline for a boundary that has to be perceived (a text field's edge, a target's edge — 3:1 against the surface); outline-variant for dividers and the edge of a card or any component holding several elements. Google: "Don't use the outline color for dividers … use outline variant instead." outline-variant may edge a chip or a button only because the content inside already carries the contrast.
  • A hyperlink in running text is primary (or tertiary for a quieter link) and underlined: the link utility.

Contrast

Level Target How
Standard Hierarchy from high- and low-contrast elements together; text 4.5:1, large text and icons 3:1, grouped non-text controls 3:1 the default scheme
Medium 3:1 minimum everywhere, without halation <html data-contrast="medium">
High 7:1 <html data-contrast="high">, or the visitor's OS setting (theme.contrast.default = system)

Every role changes with the level automatically; a component built from roles needs nothing else. Disabled states are exempt from contrast. A colour outside the roles (a hex, white, black) does not change and is the one thing that breaks a contrast level.

Sources: https://m3.material.io/styles/color/roles · https://m3.material.io/styles/color/system/how-the-system-works · https://m3.material.io/styles/color/advanced/apply-colors · https://m3.material.io/foundations/designing/color-contrast

Surfaces and elevation

M3 separates surfaces by tone first; a shadow says that something floats over the content or is being interacted with. "When it comes to applying shadows, less is more."

Level Shadow Rests here Utility
0 none The page, cards (filled, outlined), buttons (filled, tonal, outlined), button groups, icon buttons, lists, chips, tabs, sliders, the rail, a docked side sheet, a carousel, a full-screen dialog, a FAB inside the rail, an app bar at rest
1 1dp Elevated cards, elevated buttons and chips, modal bottom and side sheets, a banner shadow-elevation-1
2 3dp Menus, the navigation bar, a scrolled app bar, toolbars, rich tooltips shadow-elevation-2
3 6dp FAB and extended FAB, the FAB menu's close button, dialogs, date and time pickers, the search bar shadow-elevation-3
4 8dp Interaction only: a level-3 element on hover or while dragged shadow-elevation-4
5 12dp Interaction only shadow-elevation-5
  • Hover lifts an element one level (a FAB 3 → 4, an elevated card 1 → 2); focus and selection may too; a raised element lowers when something higher appears.
  • Overlapping panels take different surface-container roles to show separation; the roles are not tied to the levels.
  • A scrim (bg-scrim/32) brings focus to a modal over a large surface; it is never a substitute for a shadow on a small floating element.
  • On a dark surface a shadow is nearly invisible, so the tone does the work there.

Sources: https://m3.material.io/styles/elevation/overview · https://m3.material.io/styles/elevation/applying-elevation · https://m3.material.io/styles/elevation/tokens

Shape

The corner scale

Style Value Utility
None 0 rounded-corner-none
Extra small 4px rounded-corner-xs
Small 8px rounded-corner-sm
Medium 12px rounded-corner-md
Large 16px rounded-corner-lg
Large increased 20px rounded-corner-lg-increased
Extra large 28px rounded-corner-xl
Extra large increased 32px rounded-corner-xl-increased
Extra extra large 48px rounded-corner-xxl
Full a stadium or circle rounded-corner-full

Tailwind's rounded-sm, rounded-lg, rounded-full, … do not compile. The -t, -s, -e sides work (rounded-t-corner-xl for a bottom sheet).

Corner by component

Component Corner Note
Buttons, icon buttons, split button (outer), FAB menu items full a press morphs to md (xs/sm sizes), lg (md), xl (lg/xl); a selected toggle swaps round ↔ square
Connected button group full outside, sm between segments segments press to xs
FAB lg 16 (baseline 56px), lg-increased 20 (medium 80px), xl 28 (large 96px) extended FAB lg
Chips sm 8 an avatar in a chip md 12
Cards md 12 no change on hover
Text fields xs 4 (outlined: all corners; filled: top corners only)
Menus, snackbar, plain tooltip xs 4 the Expressive vertical menu rounds the focused item
Rich tooltip md 12
Dialogs xl 28 full-screen dialog none
Bottom sheet xl 28 on top
Side sheet lg 16 on the inner side
Search bar full search view xl 28 when docked, none full-screen
Date and time pickers xl 28 date cells full
Carousel items xl 28
Navigation indicator, badges, switch, slider handle, checkbox state layer full checkbox box 2px, tab indicator 3px on top
Navigation bar, app bar, docked toolbar, tabs none floating toolbar full
Segmented list rows xs inner, lg outer; a selected row lg

Rules

  • Optical roundness: a shape nested in a rounded container takes inner radius = outer radius padding (48 14 = 34), never the container's own radius.
  • Large and full corners do not belong on information-dense containers (cards, tables, text fields).
  • A press squares a round shape and rounds a square one (the components carry the morph on the fast spatial spring); nothing morphs on hover.
  • The 35 Expressive shapes (<x-shape name="…">, also the loading indicator and the standard button group's press shape) are decoration for emphasis and delight — never a carrier of meaning, never behind text-heavy content, and used sparingly.

Sources: https://m3.material.io/styles/shape/corner-radius-scale · https://m3.material.io/styles/shape/shape-morph · https://m3.material.io/styles/shape/overview-principles

Type

The typeface is Google Sans Flex for brand and plain styles (font-sans, --md-ref-typeface-brand); an application may replace it after importing the stylesheet. Each style is one utility that sets size, line height, weight, family and tracking together; text-sm, font-medium, leading-* and tracking-* do not compile.

Role Style Size / line Weight Utility Use for
Display large / medium / small 57/64 · 45/52 · 36/44 400 type-display-lg hero figures, one short marketing line; never running text
Headline large / medium / small 32/40 · 28/36 · 24/32 400 type-headline-lg page titles, section titles, a dialog's headline (headline-sm)
Title large / medium / small 22/28 · 16/24 · 14/20 400 / 500 / 500 type-title-lg app bar title (lg), card and list-section titles (md), dense headers (sm)
Body large / medium / small 16/24 · 14/20 · 12/16 400 type-body-lg paragraphs (lg for reading, md in components), supporting text (sm)
Label large / medium / small 14/20 · 12/16 · 11/16 500 type-label-lg buttons and tabs (lg), chips and navigation (md), captions and badges (sm)
  • type-emphasized-* is the same size and line height one weight step heavier (400 → 500, 500 → 700), fully rounded in Google Sans Flex, with its own tracking. M3 uses it deliberately, never by default: a selected list or menu item, a button's label on a primary action, an extended FAB, a badge, a headline given editorial weight.
  • Tracking follows Compose's TypeScaleTokens: display-large 0.2, title-medium 0.2, title-small 0.1, body-large 0.5, body-medium 0.2, body-small 0.4, label-large 0.1, label-medium and small 0.5 (sp; rem = sp/16); the emphasized set tightens a few (display-large 0, title-medium 0.15, body-large 0.15, body-medium 0.25).
  • Line length 4060 characters (max-w-prose is close; max-w-[60ch] is exact). Figures that change take tabular-nums.
  • Text must scale to 200%: containers grow, side-by-side controls stack, padding stays; components without text (progress, checkboxes) do not scale. Truncate to an ellipsis only when the full text is one tooltip or link away.
  • When customising, change the typeface or tracking, never the sizes: component layout depends on them.

Sources: https://m3.material.io/styles/typography/type-scale-tokens · https://m3.material.io/styles/typography/applying-type · https://m3.material.io/styles/typography/fonts · https://m3.material.io/foundations/writing/text-resizing · https://m3.material.io/foundations/writing/text-truncation

Motion

M3 Expressive moves on physics: every transition is a spring, and the library samples each spring into a CSS linear() easing paired with a duration. Use the pair together, or the curve is stretched over the wrong time.

Spring Damping / stiffness Duration Utility For
Spatial fast 0.6 / 800 350ms ease-spatial-fast duration-(--md-sys-motion-spatial-fast-duration) small elements: a button's press morph, a switch, a chip
Spatial default 0.8 / 380 500ms ease-spatial-default duration-(--md-sys-motion-spatial-default-duration) most position, size and shape changes
Spatial slow 0.8 / 200 650ms ease-spatial-slow duration-(--md-sys-motion-spatial-slow-duration) large surfaces: a sheet, a pane, a full-screen transition
Effects fast 1.0 / 3800 150ms ease-effects-fast duration-(--md-sys-motion-effects-fast-duration) state layers, small fades
Effects default 1.0 / 1600 200ms ease-effects-default duration-(--md-sys-motion-effects-default-duration) most colour and opacity changes
Effects slow 1.0 / 800 300ms ease-effects-slow duration-(--md-sys-motion-effects-slow-duration) large fades, a scrim
  • Spatial springs are underdamped and overshoot — that bounce is what reads as Expressive — so they carry only position, size and shape. Effects springs are critically damped and carry colour and opacity, which must never overshoot. A transition-all mixes the two and is wrong.
  • The Standard motion scheme (<html data-motion="standard">, config motion.scheme) swaps the spatial springs for stiffer ones with almost no bounce (0.9 / 1400, 700, 300; 350, 500, 750ms) for utilitarian products; effects are shared.
  • Direction: something entering decelerates (ease-emphasized-decelerate, or a spatial spring from off-screen), a permanent exit accelerates (ease-emphasized-accelerate), a temporary exit that can be recalled (a drawer, a sheet) takes ease-emphasized; exits are shorter than entrances, and larger areas move longer.
  • The cubic-bezier set (ease-standard, ease-emphasized, ease-emphasized-decelerate, ease-emphasized-accelerate, --md-sys-motion-duration-short|medium|long) is for the few transitions whose duration is fixed from outside: a view transition, an animated scroll.
  • Reduced motion zeroes every duration token, so anything animated through them turns instant; a literal duration-300 or a keyframe with its own timing ignores the visitor's setting and is a bug. Container transforms, parallax and expansions are removed, not slowed.

Sources: https://m3.material.io/styles/motion/overview · https://m3.material.io/styles/motion/overview/specs · https://m3.material.io/styles/motion/easing-and-duration/tokens-specs · https://m3.material.io/styles/motion/transitions/transition-patterns

States and targets

State Layer Utility or hook Also
Enabled none
Hover 8% of the content colour state-layer (pointer devices only) one level of elevation on floating elements
Focused 10% state-layer focus-ring (keyboard focus: a 3px secondary ring, 2px out) only one focused element at a time
Pressed 10% state-layer (:active) the shape morph on buttons
Dragged 16% state-layer with data-dragged one level of elevation
Disabled content 38%, container 12%, no state layer, not focusable disabled:text-on-surface/38 disabled:bg-on-surface/12 exempt from contrast; a FAB is hidden rather than disabled
Selected the secondary-container pair, a filled icon, the emphasized style component props (selected, aria-selected, aria-pressed) combines with hover, focus and press
  • The state layer takes the content's on- colour (on secondary-container it is on-secondary-container), is 40px on a 48px target, and only one shows at a time.
  • Every state shows two indicators, so a colour change alone is never a state: add a shape, an outline, an icon, a weight or a word (aria-selected plus the container, an error colour plus an icon and a message).
  • Targets: 48×48px minimum, 8px between targets, on every device; touch-target extends a smaller drawing to 48px. Density is an opt-in prop (dense) that steps padding by 4px and never applies to menus, snackbars, dialogs or settings controls, and never takes a target below 48px.
  • Keyboard: Tab and Shift+Tab between components in DOM order, arrows within a component (menu, tabs, grid, radio group), Enter and Space activate, Escape dismisses; a dialog moves focus in on open and back to its opener on close.

Sources: https://m3.material.io/foundations/interaction/states/state-layers · https://m3.material.io/foundations/interaction/states/applying-states · https://m3.material.io/foundations/designing/structure · https://m3.material.io/foundations/layout/grids-spacing/density

Layout and breakpoints

Layout keys on the width of the window, in M3's five window size classes; they are the only responsive variants that compile, and resources/js/breakpoints.js (from('expanded'), upTo('medium')) gives scripts the same numbers.

Class Width Variant Navigation Panes Dialogs and choices Margins
Compact below 600px the default; max-medium: for "only here" navigation bar; the rail opens as a modal 1 full-screen or basic dialog; a bottom sheet for choices 16px
Medium 600839px medium: collapsed rail (96px) 1, or 2 for low-density content at 50% each basic dialog; a menu for choices 24px
Expanded 8401199px expanded: rail, collapsed or expanded, collapsible 2 recommended; a fixed pane 360px basic dialog; menu 24px
Large 12001599px large: rail expanded 2; a fixed pane 412px basic dialog; menu 24px
Extra-large 1600px and up extra-large: rail expanded 2, or 3 with a standard side sheet (at most 400px) basic dialog; menu 24px
  • <x-scaffold> implements the navigation column; <x-list-detail> is the second pane of a list-detail layout from expanded:, <x-supporting-pane> puts a supporting pane (360px, beside the focus pane) from expanded: and below it before that. Moving up a class, ask what to reveal, divide into panes, resize, reposition or swap — never swap a component for one that does not do the same job.
  • Scaffold: bars (app bar at the top, navigation bar at the bottom: 35 destinations), rails (the navigation rail, toolbars, the FAB, on the leading edge), panes (all content), around a safety region that stays clear of the device's own chrome (--material-safe-top|bottom|left|right).
  • Canonical layouts: feed (a grid of cards that gains columns per class), list-detail (one pane on compact, two from expanded; a back button only in single-pane mode, a selected row only in two-pane mode), supporting pane (two thirds focus, one third support).
  • Bidirectionality: write logical properties (ps-4, me-2, start-0, text-start, border-s); leading and trailing icons swap, directional icons (back, send) mirror, the rail moves to the right; charts, media controls, clocks and Hebrew progress bars stay left-to-right.

Sources: https://m3.material.io/foundations/layout/breakpoints/overview · https://m3.material.io/foundations/layout/breakpoints/compact (medium, expanded, large-extra-large) · https://m3.material.io/foundations/layout/scaffold/overview · https://m3.material.io/foundations/layout/canonical-examples/overview · https://m3.material.io/foundations/layout/bidirectionality-rtl

Spacing

M3's spacing tokens are multiples of an 8px base on a 4px grid; Tailwind's spacing scale is that grid, so p-4 is space200.

Token Value Utility
space25 2px p-0.5, gap-0.5
space50 4px p-1
space75 6px p-1.5
space100 8px (the base) p-2, gap-2
space125 10px p-2.5
space200 16px p-4 — a component's padding, compact margins
space300 24px p-6 — a dialog's padding, margins from medium:
space400 32px p-8
space500 40px p-10
space600 48px p-12 — a target
space700 56px p-14
space800 64px p-16
space900 72px p-18
  • Padding and gaps live on the parent (p-4 gap-2 on the container), never as margins on children; a margin is for space beyond a container's padding or between layout regions.
  • Spacing does not scale with text: at 200% text size the same padding and gaps stay.
  • Name a gap by what it separates when a component has several (iconlabel 8px, labelsupporting text 4px).

Sources: https://m3.material.io/styles/spacing/overview · https://m3.material.io/styles/spacing/tokens · https://m3.material.io/styles/spacing/applying-spacing

Icons

<x-icon name="…"> draws a Material Symbol Rounded (weight 400, grade 0), outlined or filled, at optical size 24 or optical="20".

Axis Values In this library
Fill 0 outlined, 1 filled filled — active, selected or on state (a selected navigation item, a FAB's icon, a checked filter chip)
Weight 100700; never below 200 at 24px 400 for every icon; one weight per group
Grade 25 on dark backgrounds, 0 otherwise, positive for emphasis 0
Optical size 20 dense, 24 standard, 4048 with display type optical="20" when drawn at 20px or less (small buttons, chips, dense lists), 24 otherwise
  • An icon beside text takes the text's size and colour (size-5 beside type-label-lg, size-6 beside body) and the same optical weight; its baseline sits about 11.5% of the text size below the text's.
  • Icons stay flat and forward-facing, on the pixel grid, inside their 20px live area of the 24px canvas.
  • An icon-only control has an accessible name (aria-label, or a tooltip that names it); a decorative icon is aria-hidden; a complex icon drawn below 20px needs a label beside it.

Sources: https://m3.material.io/styles/icons/overview · https://m3.material.io/styles/icons/designing-icons · https://m3.material.io/styles/icons/applying-icons

Accessibility

  • Native elements before ARIA: <button>, <a href>, <dialog>, <input>, <select>; a styled div that fakes one needs everything re-implemented and tested.
  • Landmarks: one main, one banner, one contentinfo per page; nav, search, complementary, form, region labelled when they repeat, never with their own role in the label ("Primary", not "Primary navigation").
  • Headings: one H1 for the page, then H2H6 in order without skipping; the level is the document's structure, type-* is the appearance, and they need not match.
  • Names: an interactive icon, image or ambiguous button ("Save", "Learn more") has a name that says what it does, without the word "button"; decorative images are alt="" or aria-hidden.
  • Focus: DOM order is reading order; a dialog moves focus to its first meaningful control and returns it to the opener; grouped controls are one Tab stop with arrows inside; a keyboard shortcut is two keys, or a single key only while its component is focused.
  • Announcements: an error is tied to its field (aria-invalid, aria-describedby) and announced; a snackbar is a polite live region that never steals focus and stays while it carries an action; a loading state has a name.
  • Contrast and states: 4.5:1 text, 3:1 large text and icons and grouped controls, disabled exempt; every state has two indicators; targets 48px with 8px between; text scales to 200%; motion honours reduced motion.

Sources: https://m3.material.io/foundations/overview/principles · https://m3.material.io/foundations/designing/structure · https://m3.material.io/foundations/designing/flow · https://m3.material.io/foundations/designing/elements · https://m3.material.io/foundations/overview/assistive-technology

Don'ts

What Google's pages say not to do, and this library follows:

Don't Because Instead
Put an icon in a snackbar a snackbar is a short message with at most one action <x-toast> types choose the announcement, not a picture
Disable a FAB "if the action is unavailable, the FAB shouldn't appear" hide it
Lay radio buttons in a row a row reads as one control a vertical group; chips or a connected button group for a horizontal choice
Morph a card's corners on hover shape morphs mark a press or a selection the state layer and one level of elevation
Use outline on a divider dividers carry no contrast requirement and read too heavy border-divider (outline-variant)
Use a hex, white, black or an opacity for ink it ignores theme, contrast level and profile a role
Use Tailwind's breakpoints or scales they are not M3's values medium: … and type-*, rounded-corner-*, shadow-elevation-*, ease-*
Use segmented buttons, a navigation drawer or a bottom app bar deprecated in M3 Expressive <x-button-group connected>, the expanded rail, <x-toolbar>
Truncate without a way to read the rest an ellipsis alone is not accessible wrap, grow the container, or a tooltip
Animate with a literal duration it ignores reduced motion the paired tokens

Attribution

The rules, tables and wording here are Google's, condensed from the Material Design 3 documentation at https://m3.material.io (Foundations, Styles and Components), which Google publishes under the Creative Commons Attribution 4.0 License except as otherwise noted; the numeric token values are from the Android Open Source Project's Material 3 token files in androidx Compose (Apache License 2.0). Copyright Google LLC; Copyright The Android Open Source Project. The library's NOTICE records the same. Dates and page names are those of the site as read on 2026-09-13; the full extracted references, with every source page, are kept in the package repository under docs/reference/m3/.