Carousel
A carousel (COMPONENT_SPEC §36) shows a row of visual items that scroll horizontally. As an item scrolls, its visible part grows and shrinks between the large, medium and small sizes and the items stay pinned together: the keylines of Compose's carousels, ported from androidx.compose.material3.carousel (the Arrangement, Keylines, Strategy and snap position math in m3e-motion). Items are masked with extra-large (28dp) corners. Scrolling is the browser's, with native snapping: one item at a time for the multi-browse and hero layouts, free for the uncontained layout.
Keyboard: every item is a tab stop, and the arrow keys also move between items (Home and End to the ends); a focused item scrolls to its place. Items are APG slides ("2 of 5") in a region with the carousel role description; give the carousel a name. With reduced motion, items keep one size and are not masked. Compose's defaults put no space between items and no padding at the ends (CarouselDefaults); the examples here use the 8dp spacing and 16dp padding of the Compose samples and m3.material.io specs (item-spacing, content-padding).
Multi-browse (element)
<m3e-carousel layout="multi-browse" item-width="186"> fits large, medium and small items into the width, changing the large size as little as possible (here 412dp wide, as the Compose sample: two 178dp items, a 40dp one). Small items are 40–56dp. The Show all button is the m3.material.io way to reach every item without scrolling sideways.
Interactive items
href makes an item a link and action a button (activating it fires action with { index } from the item, bubbling through the carousel; the carousel's item-click is deprecated since 1.8 and removed in 2.0): the item then shows the state layer and ripple over its content. Static items take the focus themselves.
Uncontained (element)
layout="uncontained" item-width="186": items keep their width and the last visible one is cut off at the edge, shrinking as it leaves. It does not snap.
Hero (element)
layout="hero": one large item and a small one after it. Without item-width the large item fills the width but for the small item; with it, more large items fit. One item per swipe.
Center-aligned hero
layout="centered-hero" (Compose's HorizontalCenteredHeroCarousel): the large item between two small ones; the first and last items align with the edges instead. Fewer than three items stay start-aligned.
Full screen (CSS)
layout="full-screen": one item fills the carousel and the items scroll vertically, 16dp apart, snapping to each one (m3.material.io; Compose has no full-screen carousel). Give the carousel a height (here 360dp); ArrowUp and ArrowDown move between items.
Without JavaScript (CSS)
The m3e-css markup alone scrolls and snaps items at --m3e-comp-carousel-item-width, without the keyline sizes or masks (the same layout reduced motion shows).
React
<Carousel layout itemWidth itemSpacing contentPadding aria-label> with <CarouselItem href onPress> children renders the same DOM as the element; its ref has scrollToItem(index) and currentItem.
Sources
androidx Compose Material3 1.5.0-beta01 (19991f2c): carousel/Carousel.kt (CarouselDefaults L813–825: small items 40–56dp, item spacing and content padding 0dp L819 / L822), Arrangement.kt, Keylines.kt, KeylineList.kt, Strategy.kt, KeylineSnapPosition.kt, CarouselState.kt (animateScrollToItem's spring(), L101), CarouselItemScope.kt, CarouselSamples.kt (the extra-large mask L130; 8dp between items and 16dp at the ends, L119–120) and the androidHostTest suites the keyline math is checked against; animation-core AnimationSpec.kt and VectorizedAnimationSpec.kt. There is no CarouselTokens.kt: the values are generated into components/carousel-defaults.css (lines in PARITY.md).
m3.material.io Carousel (Specs, Guidelines, Accessibility; token DB TOKEN_TABLE.43a124d2adc8a2ef, md.comp.carousel-item: the item mask and state layer) for the full-screen layout and reduced motion. SOURCES register #53, #82 (Compose's 0dp defaults; the docs use the samples' 8 / 16dp, DECISIONS D19 (19)), #83 (no corner radius full screen, D19 (20)) and #84 (D19 (21)).