1.7.0
Minor changes
-
Badges (M9, COMPONENT_SPEC §34; Compose
BadgeandBadgedBox): the 6dp dot and the 16dp large badge (label small, 4dp padding, up to four characters) in the error colors, placed on the anchor's top-end corner asBadgedBoxplaces them (the dot 6dp inside it, a large badge 12dp before the end and 2dp above the top; mirrored in RTL), with a CSS hook for thebadgeBounds()rulers that navigation items and tabs will use. m3e-react<Badge count max>writes counts above 999 as999+(m3e-motionbadgeText) and<BadgedBox badge>wraps the anchor. The badge carries visually hidden text that joins the accessible name of its item ("New notification" for the dot, the count otherwise, orlabel); the visible digits arearia-hidden. Newcomponents/badge-defaults.csstokens (theBadge.ktvalues Compose renders) and m3e-cssbadge.css. No custom element: navigation bar, rail, suite and tab badges follow separately. -
Bottom sheets (M9, COMPONENT_SPEC §30): Compose's
ModalBottomSheet(a native modal<dialog>named "Bottom Sheet" over the 0.32 scrim; the page inert and its scroll locked, Tab kept inside, focus on the drag handle and back to the opener; Escape partially expands an expanded sheet, else hides it, as the scrim does) andBottomSheet(the standard sheet, fixed to the bottom of its positioned container, with theBottomSheetScaffoldpeek height as an option). The sheet is surface-container-low with extra-large top corners, at most 640dp wide, centered and flush with the bottom; it opens partially expanded (half the container, or the whole sheet when it is shorter) or, withskipPartiallyExpanded, expanded. Show / expand run on the default spatial spring, hide / partially expand on the fast effects spring (both jump under reduced motion), the scrim on the default effects spring; drags settle with Compose's thresholds (56dp from the anchor behind, 125dp/s, a dampened fling near Hidden) on the default spatial spring started at the release velocity. The drag handle is a 32 × 48dp button with its built-in "Drag handle" tooltip: a click expands a partially expanded sheet and dismisses an expanded one; ArrowUp / ArrowDown expand and collapse it. Newcomponents/bottom-sheet-defaults.csstokens, m3e-cssbottom-sheet.css, m3e-motion's N-anchor anchored-draggable model (DraggableAnchors,computeTarget,AnchoredDraggableAnimation; reference-tested against the androidx anchored-draggable and sheet tests and against the navigation drawer's two-anchor target selection) andSheetState, the m3e-elements<m3e-bottom-sheet>andbottom-sheet-layout(BottomSheetLayout) entries, and m3e-react<BottomSheet>and<ModalBottomSheet>. The navigation drawer's pointer drags now run on the drag helper it shares with the sheets (no change in behavior). -
Carousel (M9, COMPONENT_SPEC §36): the multi-browse, uncontained and center-aligned hero carousels of Compose Material3, the start-aligned hero, and a CSS-only full-screen layout. m3e-motion ports Compose's carousel math (Arrangement, keylines, Strategy, snap positions and the per-item mask and translation), checked against the Compose host tests and a JVM reference; items grow and shrink as they scroll, masked with extra-large corners, and snap natively one at a time to their keylines (the uncontained layout scrolls freely). Every item is a tab stop and the arrow keys move between them (WAI-ARIA carousel and slides); link and button items show the state layer and ripple; reduced motion keeps every item at one size. New
components/carousel-defaults.csstokens, m3e-csscarousel.css, the m3e-elements<m3e-carousel>/<m3e-carousel-item>andcarousel-layout(CarouselLayout) entries, and m3e-react<Carousel>/<CarouselItem>. -
Dialogs (M9, COMPONENT_SPEC §29): the alert dialog (Compose
AlertDialog: an optional centered icon, a headline, supporting text and the dismiss / confirm buttons, end-aligned and stacked with the confirm button on top when they do not fit, in a 280–560dp surface-container-high surface with extra-large corners and no shadow), custom content (ComposeBasicAlertDialog) and the full-screen dialog (m3.material.io; Compose has none: a 56dp header with a close button, the headline and the confirming action, filling the window below 600dp and laid out as a basic dialog from 600dp, the header taking surface-container while the content scrolls). Each is a native<dialog>opened withshowModal(): the page is inert, the page scroll locks, Tab stays inside, focus starts on the first control and returns to the opener; Escape, the 32% scrim and the close button ask to close (cancelable, as Compose'sonDismissRequest). The alert dialog has thealertdialogrole and is named by its headline and described by its text; the others are plain dialogs named by the headline or "Dialog". Motion: the scrim fades on the default effects spring; the dialog slides in and its surface grows as Material Web's dialog does (fades only under reduced motion). Newcomponents/dialog-defaults.csstokens (theAlertDialog.ktvalues Compose renders, the modal scrim fade, Material Web 2.5.0's dialog motion and the m3.material.io full-screen dialog), m3e-cssdialog.css, the m3e-elements<m3e-dialog>anddialog-layout(DialogLayout) entries, and m3e-react<AlertDialog>,<BasicAlertDialog>and<FullScreenDialog>. Shared helper:base/modal.tsgainsModalSession(scroll lock, Tab trap, Escape, initial focus and focus return) for the modals that follow. -
Badges on navigation destinations and tabs (M9 B2; COMPONENT_SPEC §13, §14, §16, §17, §34):
badge(the dot for""/true, a count with999+above 999, or short text) andbadge-label/badgeLabel(the visually hidden text, read after the label: "Inbox 8", "Chat New notification") on<m3e-navigation-item>and<m3e-tab>, and on the ReactNavigationDestination(short navigation bar, wide and modal rails, navigation suite, the legacy bar and rail) andTabItem/<Tab>. A ComposeBadgesits on the destination's icon (BadgedBox, asNavigationSuiteScaffoldbuilds it) and at the end of a tab's label (on the icon when the label is hidden), kept inside narrow items and tabs like Compose'sbadgeBounds()(CSS for the navigation items, TabsLayout for tabs; a leading-icon tab's badge is not clamped, asLeadingIconTabhas no bounds). The navigation suite's drawer type keeps showingbadgeas trailing text. m3e-motion addsbadgeValueText,badgeLabelTextand theBadgeValuetype. -
Pull to refresh (M9, COMPONENT_SPEC §38): Compose Material3's
PullToRefreshBox. A touch or pen pull down at the top of a scroll container (overscroll contained) brings the indicator down, half the drag and slowing past the 80dp threshold; a release past it asks for a refresh, and the indicator rests at the threshold while the app refreshes. m3e-motion ports Compose's pull math and arrow (checked against a JVM reference). The default indicator is Compose's arrow then a circular progress; the loading indicator variant drives contained loading indicators. Mouse drags never pull: a visible Refresh button is the keyboard path. Newcomponents/pull-to-refresh-defaults.csstokens, m3e-csspull-to-refresh.css, the m3e-elements<m3e-pull-to-refresh>andpull-to-refresh-layout(PullToRefreshLayout) entries, and m3e-react<PullToRefresh>. -
Segmented button (M9, COMPONENT_SPEC §37), deprecated from the start (DECISIONS D4: shipped until 2.0 for migration; use the connected button group): Compose Material3's
SingleChoiceSegmentedButtonRow/MultiChoiceSegmentedButtonRowwithSegmentedButtonon native radios and checkboxes (no custom element). Equal-width buttons overlapping by their 1dp outline in a 48dp row, full corners on the outer ends, secondary container when selected; the check fades and scales in on the springs while the label slides aside, and leaves at once; an icon shown while unselected cross-fades with it. Newcomponents/segmented-button-defaults.csstokens (theSegmentedButton.ktvalues Compose renders), m3e-csssegmented-button.css(with the state-layer, focus-ring andripple.jshooks), and m3e-reactSingleChoiceSegmentedButtonRow,MultiChoiceSegmentedButtonRowandSegmentedButton, marked@deprecatedand warning once in development. -
Side sheets (M9, COMPONENT_SPEC §31; D8: Compose has no side sheet, m3.material.io is the only reference and every value is
TODO(verify)against it). The standard side sheet is an<aside>at the end of a flex row that takes its width from the row while open, so the content beside it shrinks; the modal side sheet is a native modal<dialog>at the window's end edge over the 0.32 scrim (the page inert and its scroll locked, Tab kept inside, focus on its first button and back to the opener);adaptiveis modal below 600dp (the medium window size class) and standard from it. From the m3.material.io token DB and Specs: 256dp wide by default and at most 400dp, surface (standard) or surface-container-low with 16dp start corners and a level 1 shadow (modal), adetachedoption inset by 16dp with all corners rounded, an optional divider in outline, a header with an optional back button, the title-large headline and the required close button, and optional start-aligned bottom actions. The sheets open on the default spatial spring and close on the fast effects spring, the navigation drawer's motion mirrored to the end edge (no drags); the close button, Escape and the scrim ask to close. Newcomponents/side-sheet-defaults.csstokens, m3e-cssside-sheet.css, the m3e-elements<m3e-side-sheet>andside-sheet-layout(SideSheetLayout) entries, and m3e-react<SideSheet>. -
Snackbar (M9, COMPONENT_SPEC §32): Compose's
Snackbar(inverse surface, extra-small corners, the level 3 shadow; the text, then an inverse-primary text-button action and a dismiss icon button with its built-in "Dismiss" tooltip at the end, or the action under the text; 48dp for one line, 68dp for two, at most 600dp wide; the padding-basedisSnackbarStylingFixEnabledlayout) and its host (Compose'sSnackbarHost/SnackbarHostState): one snackbar at a time from a first-in, first-out queue,showSnackbar()resolving with'action-performed'or'dismissed', 4s / 10s / indefinite durations (indefinite with an action), the timer paused while hovered or focused, Escape dismissing the focused snackbar,focus()to reach it from an app shortcut, focus returned when it leaves; the current snackbar scales and fades in on the fast springs while the previous one fades out. The host is a polite live region fixed to the bottom center of the window, raised by--m3e-comp-snackbar-host-bottom-offset(above a FAB). Newcomponents/snackbar-defaults.csstokens, m3e-csssnackbar.css, the m3e-elements<m3e-snackbar-host>andsnackbar-layout(SnackbarHostState,SnackbarHostController) entries, and m3e-reactuseSnackbarHostState(),<SnackbarHost>and<Snackbar>. -
Tooltips (M9, COMPONENT_SPEC §33; Compose
PlainTooltip,RichTooltipandTooltipBox): plain tooltips (inverse surface, up to 200dp) and rich tooltips (subhead, supporting text and a text-button action, up to 320dp, level 2 shadow), with Compose's opt-in caret. Compose's behavior: mouse hover shows a tooltip at once and it stays while the anchor or the tooltip is hovered, hiding 1.5 s after the pointer leaves both (m3.material.io); the anchor'saria-describedbypoints at the tooltip unless its text equals the anchor's accessible name (then the tooltip isaria-hidden); a rich tooltip with an action is a non-modal dialog; a touch long press shows it until the press ends (at least 1.5 s); keyboard focus shows it until focus leaves; Escape and a click outside hide it; one tooltip at a time (the global mutex and its priorities);show()hides a non-persistent tooltip after 1.5 s. Placement portsTooltipPositionProviderImpl(above by default, flipped below at the window top; below, left, right, start, end) and the caret placement, measured from the anchor's 48dp minimum interactive bounds; the tooltip scales in from 0.8 on the fast spatial spring and fades on the fast effects spring. Newcomponents/tooltip-defaults.csstokens (theTooltip.kt/internal/BasicTooltip.ktvalues Compose renders), m3e-motiontooltipPosition/tooltipCaret, m3e-csstooltip.css, the m3e-elements<m3e-tooltip>andtooltip-popup(TooltipController,TooltipPopup) entries, and m3e-react<TooltipTrigger>,<PlainTooltip>and<RichTooltip>. Shared helper: the menu popup's popover, spring and reposition engine moves intoAnchoredPopup, whichMenuPopupnow extends (no change to menus).
Patch changes
-
Button group (M9 follow-up T2, fidelity fix): the overflow ("More options") icon button now has the plain tooltip Compose builds into
ButtonGroupDefaults.OverflowIndicator— the button's name (overflow-label/overflowLabel), above it, shown on hover, keyboard focus or a long press and hidden 1.5s after the pointer leaves, as every tooltip does. It repeats the button's name, so it isaria-hiddenand not anaria-describedbytarget.<m3e-button-group>renders the.m3e-tooltipafter the overflow button and imports thetooltip-popupentry when that button first renders; m3e-react's<ButtonGroup>uses<TooltipTrigger>+<PlainTooltip>.