Pular para o conteúdo

Carousels

components specs/components/carousels.kmd

Horizontally scrolling stack of items, optimized for browsing a collection at a glance. Material parity (`/components/carousels`). Covers Hero, Multi-browse, and Contained layouts; snap behavior; swipe gestures; accessibility for sequential item navigation.

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

Spec — Carousels

Facet Visual of Koder Design. Material parity: https://m3.material.io/components/carousels.

3 layout patterns

LayoutItem count visibleUse
Hero1 large + 1 preview edgeFeatured / spotlight ("Featured project")
Multi-browse3-5 mixed sizesBrowse-heavy ("Recent files")
Contained2-4 equal sizesCard-like grid in a strip

Pick by intent: Hero for "look at THIS"; Multi-browse for "scan across"; Contained for "uniform set you can scroll through".

Anatomy (Hero layout)

←─                                                      →─
   ┌──────────────────────────────────┐  ┌─────┐
   │                                  │  │     │
   │       Featured item              │  │ next│
   │      (full width minus           │  │ peek│
   │       16 px edge for peek)       │  │     │
   │                                  │  │     │
   └──────────────────────────────────┘  └─────┘
        ●  ○  ○  ○  ○                       ← page indicator
  • Item radius: 12 px (matches card defaults)
  • Item gap: 8 px
  • Edge peek: 16 px (shows ~24 px of next/previous item)
  • Page indicator: dots, 8 px circles, 4 px gap
  • Snap: item-edge to container-edge

R1 — Multi-browse layout

Mixed item widths in a single row. Material reference: large, medium, small repeating pattern.

SlotWidthPosition
Large200 dpCenter / start
Medium140 dpTrailing large
Small80 dpAt edges, indicates more

Items resize as they scroll across the visible area: focused = large, adjacent = medium, edges = small. Animation per scroll position.

R2 — Contained layout

Fixed item width, all equal. Width inferred from container:

Container widthItems visibleItem width
Compact (< 600 dp)1.2~80% of container
Medium (600-839 dp)2.2~45%
Expanded (≥ 840 dp)3.2~30%

The .2 partial visible signals scrollability.

R3 — Snap behavior

  • Snap to item: scroll-end snaps to nearest item edge
  • Velocity threshold: fast flick passes through multiple items; slow drag snaps to nearest
  • Disable snap: opt-out via prop when free-scroll is preferred (rare; document why)
  • Snap uses motion.kmd emphasized-decelerate easing (~350 ms)

R4 — Page indicator

Dots below carousel show:

  • Total item count (one dot per item, or grouped per "page" if > 10)
  • Current focus position (filled dot)
Item countIndicator
≤ 10One dot per item
11-30Grouped per visible page (e.g., 5 pages of 3 items)
> 30"1 / 47" text indicator instead of dots

Tappable dots: tap dot scrolls to that item (motion-medium, ~300 ms).

R5 — Navigation controls

SurfaceControls
MobileSwipe + dots (no arrow buttons)
Tablet portraitSwipe + dots
DesktopArrow buttons (◂ ▸) at edges + dots + keyboard

Arrow buttons appear on hover (default) OR always visible (opt-in). Disabled-state arrow when at start / end (38% opacity).

R6 — Keyboard navigation

When carousel has focus:

  • Arrow Left / Right: scroll to previous / next item (animated)
  • Home / End: jump to first / last
  • Tab: focus moves to focused item; Tab again moves OUT of carousel to the next focusable element after the carousel
  • Enter / Space on item: triggers item's action (open, etc.)

R7 — Item content

Items are normally cards or images. Each item must have:

  • A defined aspect ratio (16:9 / 4:3 / 1:1 — pick one per carousel)
  • A focusable target (whole item is the target by default)
  • An accessible name (aria-label or visible heading)
  • Loading state: skeleton matching item shape until content loads

R8 — Accessibility

  • Container: role="region" + aria-roledescription="carousel" + aria-label describing collection
  • Items: role="group" + aria-roledescription="slide" + aria-label="3 of 7" (position + total)
  • Page indicator: role="tablist"; each dot role="tab" with aria-selected="true" on current
  • Live region: when item changes via auto-advance, announce new item's name (polite live region)
  • Auto-advance ALWAYS pauses on hover, focus, or prefers-reduced-motion

R9 — Auto-advance (opt-in)

Off by default. When enabled:

  • Interval: 5-8 seconds per item (configurable; never < 4 s)
  • Pause on hover / focus / touch-down
  • Resume only after user interaction settles
  • Always pair with manual controls (dots + swipe)
  • Disabled when prefers-reduced-motion: reduce

Auto-advance is for promotional / passive carousels only. Don't auto-advance functional content (settings, lists).

R10 — Animation

  • Item scroll: 1:1 with finger drag; momentum on release
  • Snap settle: motion-emphasized-decelerate (~350 ms)
  • Arrow click: scroll by one item, motion-medium (~250 ms)
  • Multi-browse resize: items grow / shrink as they cross focus position (continuous interpolation)
  • Reduced motion: no resize animation, no auto-advance, instant snap

R11 — Per-preset variation

PresetVisual
material312 px corners, edge peek, multi-size in Multi-browse
material24 px corners, uniform sizes, no peek by default
ios_cupertinoPage dots only (no arrows even on desktop), flush items
gnomeAdwaita carousel with side fade, integrated arrow buttons
windows_11Wide layout with arrow chevrons at sides, no dot indicator
brutalistSharp corners, no peek, hard snap (no smooth scroll)
terminal_classicSequential [1/7] indicator + Arrow Left/Right navigation only

R12 — Forbidden patterns

  • ❌ Carousels with > 30 items (use grid / list instead)
  • ❌ Carousels as primary navigation (use tabs or nav components)
  • ❌ Hiding the page indicator entirely when count > 1 (user can't see "there's more")
  • ❌ Auto-advance < 4 s (too fast to read)
  • ❌ Auto-advance for forms or settings content
  • ❌ Carousel inside a horizontally-scrolling parent (nested horizontal scroll = unusable)
  • ❌ Carousel without keyboard navigation
  • ❌ Carousel without prefers-reduced-motion handling
  • ❌ Items with variable aspect ratios (jarring resize on scroll)
  • themes/motion.kmd — emphasized-decelerate easing for snap
  • themes/shape.kmd — item corner radius
  • themes/color-roles.kmd — indicator dot color
  • components/cards.kmd — item content pattern
  • app-layout/window-size-classes.kmd — Contained items-visible rules
  • foundations/elements.kmd — Container + Navigator families

Referências