Figma: arrows in Speakers 5624:1085, Testimonials 5597:16837, Projects 5597:21587, Team 5597:20455
Steps
- Build everything fresh in
lib/Components/museum/. Don't import or change the old packages/ui carousel pieces.
CarouselArrow: gold gradient circle + brown arrow. Props direction, size: "sm" | "lg", disabled (dimmed), aria-label. Hover, active and focus states.
useCarousel<T>(items, { loop }) returns { index, item, next, prev, goTo, canPrev, canNext, direction }.
<CarouselSwap animated={boolean}>: crossfade + small slide in direction when animated, an instant swap when not (SM passes animated={false}). Reduced motion falls back to fade only.
useSwipe(ref, { onLeft, onRight }): a pointer-event swipe with a ~40px threshold that doesn't block vertical scrolling (for SM).
useHorizontalGallery(ref) for Team: one page per arrow click (scrollBy), canPrev/canNext from scroll position, scroll-snap, hidden scrollbar, native trackpad/touch.
- Keyboard ←/→ inside the carousel region (
role="region", aria-roledescription="carousel", aria-live="polite").
/dev/carousel demo with 0, 1 and many items.
Acceptance criteria
Figma: arrows in Speakers
5624:1085, Testimonials5597:16837, Projects5597:21587, Team5597:20455Steps
lib/Components/museum/. Don't import or change the oldpackages/uicarousel pieces.CarouselArrow: gold gradient circle + brown arrow. Propsdirection,size: "sm" | "lg",disabled(dimmed),aria-label. Hover, active and focus states.useCarousel<T>(items, { loop })returns{ index, item, next, prev, goTo, canPrev, canNext, direction }.<CarouselSwap animated={boolean}>: crossfade + small slide indirectionwhenanimated, an instant swap when not (SM passesanimated={false}). Reduced motion falls back to fade only.useSwipe(ref, { onLeft, onRight }): a pointer-event swipe with a ~40px threshold that doesn't block vertical scrolling (for SM).useHorizontalGallery(ref)for Team: one page per arrow click (scrollBy),canPrev/canNextfrom scroll position,scroll-snap, hidden scrollbar, native trackpad/touch.role="region",aria-roledescription="carousel",aria-live="polite")./dev/carouseldemo with 0, 1 and many items.Acceptance criteria