A horizontally scrolling row of DS components — promo banners, paged slides, home-screen shelves.
Promotions





A horizontally scrolling row of DS components — promo banners, paged slides, home-screen shelves.





CarouselContainer lays a row of items out horizontally and lets the user scroll it. It owns the row — width, insets, gaps, snapping, the position indicator and autoplay — and nothing inside the items: each item's content slot takes any DS component. The item width is computed from the container's width, so one configuration serves every screen.









The mode — Peek, Paged, Shelf — is the style axis; it sets the item width, the snapping and the indicator (see Overview and Layout). CarouselContainer paints nothing of its own except the page indicator: the colour of every item comes from its content. The states differ by mode, so each mode lists its own below; the rest state is Standard in every mode.
pageIndicator: overlay (Figma Background=on); Below has no fill.

















































pageIndicator: overlay puts the dots over the page's bottom edge, on a --surface-white-overlay pill; the row is as tall as its items.For dark or photo banners where the height counts — the pill reads on them; on a light banner the white 16% all but disappears. Not for pages with text or a button at the bottom centre.








pageIndicatorAlign — center by default, start or end; in both placements. Above: Below at the start, Overlay at the end.At the start or end the indicator sits var(--sp-s12) in from the edge inset. Start is the left edge in LTR and the right in RTL.




pageIndicator: none turns the page indicator off — the dots and the slot they sit in under the row are gone.The page still snaps and each item still announces its position, but nothing on screen shows that the row scrolls.

stretchItems: true — the items share the container width minus two var(--sp-s20) edge insets equally: (360 − 40 − 2 · 8) / 3 ≈ 101.Applies only while the items fit; once they overflow, the item width applies and the row scrolls.
stretchItems it takes the whole row.
A container with a scrolling track of CarouselItems, each with one content slot, and — in Paged — a decorative page indicator. The section title above the row is a separate component.




Every offset is an SP token, and the item width is computed from the container width W — the redlines are drawn at W 360. The item is shown as its empty content slot.
pageIndicatorAlign: start / end moves it to an edge, mirrored in RTL.
stretchItems shares the row between them.




Peek for promo banners and featured offers, two per view for paired cards; Paged for a short sequence of full-width slides where the position matters; Shelf for category tiles, rides and routes. Not for content the user compares side by side, and not as the only path to a key action — items off-screen are easy to miss. Dots inside a card, where the card's content pages, are a different pattern.





2 hours
3 hours
2 hours
2 hours


















The container is a named row; each item is one stop that says where it is in the row. Moving focus scrolls the row — a screen-reader user never has to swipe the row itself to reach an item.




CollectionInfo, "in list, 5 items". VoiceOver: the heading, then accessibilityContainerType = .list — "list start". Web: <section aria-roledescription="carousel" aria-label="Promotions">, with "carousel" localised.
CollectionItemInfo gives the position. VoiceOver: one element whose label ends in a localised "2 of 5"; .button set explicitly — combining does not add it. Web: role="group" aria-roledescription="slide" aria-label="2 of 5", the content follows. An item with several controls is not a stop of its own: the controls are focused one by one and the first carries the position.
clearAndSetSemantics {}, VoiceOver accessibilityHidden(true), web aria-hidden="true" on spans, never buttons inside a hidden container. The item announces the position.
accessibilityScroll) and the app posts a localised "Page 2 of 5" — app-supplied, not produced by the platform. TalkBack: ACTION_SCROLL_FORWARD / BACKWARD page the row and TalkBack speaks its own "showing items 2 to 3 of 5". In RTL forward moves toward the visual left.
tabindex="0", named after the row, with a focus ring; Left / Right move it item by item (mirrored in RTL), Home / End to the ends. No Previous / Next buttons (owner, 2026-11-12): Paged has no single-pointer alternative to the swipe — the WCAG 2.5.1 gap is accepted.