Skip to content

feat(Carousel): add new component#190

Open
johnleider wants to merge 12 commits intomasterfrom
claude/carousel-component-vuetify-Apbrs
Open

feat(Carousel): add new component#190
johnleider wants to merge 12 commits intomasterfrom
claude/carousel-component-vuetify-Apbrs

Conversation

@johnleider
Copy link
Copy Markdown
Member

Summary

Adds a new Carousel component to the semantic components library. This is a headless carousel built on CSS scroll-snap with support for multi-slide display, partial-slide peeking, drag/swipe navigation, and programmatic control via previous/next buttons.

Key Changes

  • CarouselRoot: Root component that creates and provides step context for carousel navigation. Supports circular/bounded modes, orientation (horizontal/vertical), multi-slide display (perView), gap spacing, and peek configuration.

  • CarouselViewport: Scroll-snap container that handles native drag/swipe interaction and synchronizes scroll position with step selection state. Exposes isDragging state and manages scroll-to-selection synchronization.

  • CarouselSlide: Individual slide component that registers with the carousel context. Provides selection state, visibility tracking, and automatic sizing based on perView, gap, and peek values.

  • CarouselPrevious & CarouselNext: Navigation button components that automatically disable at carousel boundaries in non-circular mode. Expose isAtEdge state for styling.

  • Comprehensive test suite: 1000+ lines of tests covering rendering, navigation (next/prev/first/last), circular/bounded modes, disabled states, mandatory selection, slot props, ARIA attributes, data attributes, and inline styles.

  • Documentation: Full component documentation with anatomy, examples (basic, multi-slide, peek), recipes (circular, vertical, disabled), accessibility details, and FAQ.

  • Examples: Three example implementations demonstrating basic carousel, multi-slide display, and peek functionality.

Implementation Details

  • Built on Vue 3 composition API with renderless/headless design pattern
  • Uses step context from createStep composable for selection management
  • Implements WAI-ARIA carousel pattern with proper roles and ARIA attributes
  • Exposes comprehensive slot props for flexible styling and interaction
  • Automatic slide sizing calculation accounting for gaps and peek values
  • Scroll position synchronization with debouncing to prevent feedback loops
  • Data attributes (data-selected, data-active, data-disabled, data-index) for CSS-only styling
  • Supports both horizontal and vertical orientations
  • Circular navigation mode with wrapping from last to first slide

Component maturity updated from "draft" to "preview" with version 0.3.0.

https://claude.ai/code/session_01LYmjuphJqS2njPANKAoxPr

claude added 2 commits April 12, 2026 21:46
Implements a compound carousel component built on createStep with CSS
scroll-snap for native drag/swipe navigation. Supports multi-slide
display (perView), partial-slide peeking, circular navigation, and
full WAI-ARIA carousel pattern compliance.

Components: Root, Viewport, Slide, Previous, Next
Tests: 32 passing (registration, navigation, ARIA, data attributes, SSR)
Docs: page, basic/multi-slide/peek examples, recipes

https://claude.ai/code/session_01LYmjuphJqS2njPANKAoxPr
Follows the pattern from TabsRoot where defineEmits is declared
alongside defineModel for 'update:model-value'.

https://claude.ai/code/session_01LYmjuphJqS2njPANKAoxPr
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 12, 2026

Open in StackBlitz

commit: e43fbf6

@johnleider johnleider self-assigned this Apr 13, 2026
@johnleider johnleider modified the milestone: v1.0.0 Apr 13, 2026
@johnleider johnleider changed the title feat: add Carousel component with scroll-snap and multi-slide support feat(Carousel): add new component Apr 13, 2026
- Fix double-fire bug from v-bind="attrs" on non-renderless children
- Fix circular navigation dying with perView > 1
- Add mouse drag with smooth snap-to-slide on release
- Add autoplay prop with play/stop/pause/resume controls
- Rename CarouselSlide to CarouselItem for consistency
- Switch examples to data-attribute CSS selectors
- Move all imports from <script setup> to first <script> block (all 5 files)
- Replace manual document.addEventListener with useToggleScope + useDocumentEventListener in Viewport
- Add aria-disabled to CarouselNext/Previous (matches Pagination pattern)
- Wire up useLocale for all aria-labels (Carousel.next, Carousel.prev, Carousel.slide)
- Rename abbreviated variables (idx → index, pv → perView) in CarouselItem
- Switch onUnmounted → onBeforeUnmount for unregister cleanup
- Add defineEmits comment explaining vue-devtools requirement
- Update components.md rules: import enforcement, locale requirement, aria-disabled typing, onBeforeUnmount, defineEmits guidance
gap and peek are styling concerns that break the headless contract.
Consumers now control these via CSS (gap, padding utilities) and
slide sizing (flex/width classes). The viewport measures actual
slide offsets from the DOM for scroll-snap math instead of
calculating from prop values.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants