mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 05:05:38 -04:00
Replace CSS overflow scroll with Embla Carousel + wheel gestures plugin
Title rows (TitleRow, ContinueWatchingList) now use the shadcn Carousel component backed by Embla with embla-carousel-wheel-gestures, enabling mouse wheel horizontal scrolling and drag-to-scroll on desktop while preserving touch swipe, stagger animations, and existing layout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { WheelGesturesPlugin } from "embla-carousel-wheel-gestures";
|
||||
import { motion } from "motion/react";
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
} from "@/components/ui/carousel";
|
||||
import {
|
||||
ContinueWatchingCard,
|
||||
type ContinueWatchingItemProps,
|
||||
@@ -28,16 +34,25 @@ export function ContinueWatchingList({
|
||||
}) {
|
||||
return (
|
||||
<motion.div
|
||||
className="feed-scroll -mx-4 flex gap-4 overflow-x-auto px-4 pb-2 sm:-mx-0 sm:px-0"
|
||||
variants={staggerContainer}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
>
|
||||
{items.map((item) => (
|
||||
<motion.div key={item.title.id} variants={staggerItem}>
|
||||
<ContinueWatchingCard item={item} />
|
||||
</motion.div>
|
||||
))}
|
||||
<Carousel
|
||||
opts={{ align: "start", dragFree: true, containScroll: "trimSnaps" }}
|
||||
plugins={[WheelGesturesPlugin({ forceWheelAxis: "x" })]}
|
||||
className="-mx-4 sm:-mx-0"
|
||||
>
|
||||
<CarouselContent className="px-4 sm:px-0">
|
||||
{items.map((item) => (
|
||||
<CarouselItem key={item.title.id} className="basis-auto pl-4">
|
||||
<motion.div variants={staggerItem}>
|
||||
<ContinueWatchingCard item={item} />
|
||||
</motion.div>
|
||||
</CarouselItem>
|
||||
))}
|
||||
</CarouselContent>
|
||||
</Carousel>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { WheelGesturesPlugin } from "embla-carousel-wheel-gestures";
|
||||
import { motion } from "motion/react";
|
||||
import { TitleCard } from "@/components/title-card";
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
} from "@/components/ui/carousel";
|
||||
|
||||
interface TitleRowItem {
|
||||
tmdbId: number;
|
||||
@@ -43,28 +49,36 @@ export function TitleRow({ heading, icon, items }: TitleRowProps) {
|
||||
<h2 className="font-display text-xl tracking-tight">{heading}</h2>
|
||||
</div>
|
||||
<motion.div
|
||||
className="feed-scroll -mx-4 flex gap-4 overflow-x-auto px-4 pb-2 sm:-mx-0 sm:px-0"
|
||||
variants={staggerContainer}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
>
|
||||
{items.map((item) => (
|
||||
<motion.div
|
||||
key={`${item.type}-${item.tmdbId}`}
|
||||
variants={staggerItem}
|
||||
className="w-[140px] shrink-0 sm:w-[160px]"
|
||||
>
|
||||
<TitleCard
|
||||
tmdbId={item.tmdbId}
|
||||
type={item.type}
|
||||
title={item.title}
|
||||
posterPath={item.posterPath}
|
||||
releaseDate={item.releaseDate}
|
||||
voteAverage={item.voteAverage}
|
||||
href={`/titles/tmdb-${item.tmdbId}-${item.type}`}
|
||||
/>
|
||||
</motion.div>
|
||||
))}
|
||||
<Carousel
|
||||
opts={{ align: "start", dragFree: true, containScroll: "trimSnaps" }}
|
||||
plugins={[WheelGesturesPlugin({ forceWheelAxis: "x" })]}
|
||||
className="-mx-4 sm:-mx-0"
|
||||
>
|
||||
<CarouselContent className="px-4 sm:px-0">
|
||||
{items.map((item) => (
|
||||
<CarouselItem
|
||||
key={`${item.type}-${item.tmdbId}`}
|
||||
className="basis-auto pl-4 w-[140px] shrink-0 sm:w-[160px]"
|
||||
>
|
||||
<motion.div variants={staggerItem}>
|
||||
<TitleCard
|
||||
tmdbId={item.tmdbId}
|
||||
type={item.type}
|
||||
title={item.title}
|
||||
posterPath={item.posterPath}
|
||||
releaseDate={item.releaseDate}
|
||||
voteAverage={item.voteAverage}
|
||||
href={`/titles/tmdb-${item.tmdbId}-${item.type}`}
|
||||
/>
|
||||
</motion.div>
|
||||
</CarouselItem>
|
||||
))}
|
||||
</CarouselContent>
|
||||
</Carousel>
|
||||
</motion.div>
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user