Replace Carousel with ScrollArea, remove embla-carousel dependency

- Delete carousel.tsx and replace all Carousel/CarouselContent/CarouselItem
  usage across title rows, cast carousel, continue watching, and explore
  sections with ScrollArea + scrollFade horizontal scroll
- Update ScrollArea to accept a `scrollFade` prop that renders a
  gradient edge overlay instead of the old per-site absolute div hack
- Remove "use client" directive from title-row and cast-carousel now
  that they have no client-side hooks
- Delete unused resizable.tsx; inline TypeBadge icon into TitleHero
  and delete the standalone type-badge.tsx file
- Add TitleTheme component for per-title accent color CSS injection
- Swap IconSparkles → IconThumbUp in recommendations section and grid
- Simplify ambient glow to a single size (remove mobile breakpoint override)
This commit is contained in:
2026-03-08 09:53:12 -04:00
parent 7ed172d675
commit 02466e94f9
20 changed files with 207 additions and 576 deletions
@@ -1,8 +1,4 @@
import {
Carousel,
CarouselContent,
CarouselItem,
} from "@/components/ui/carousel";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
ContinueWatchingCard,
type ContinueWatchingItemProps,
@@ -14,22 +10,22 @@ export function ContinueWatchingList({
items: ContinueWatchingItemProps[];
}) {
return (
<Carousel
opts={{ align: "start", dragFree: true, containScroll: "trimSnaps" }}
className="-mx-4 sm:-mx-0 [&>[data-slot=carousel-content]]:px-px"
<ScrollArea
scrollFade
className="-mx-4 sm:-mx-0 [&_[data-slot=scroll-area-content]]:px-px"
>
<CarouselContent className="px-4 sm:px-0">
<div className="flex gap-4 px-4 py-2 sm:px-0">
{items.map((item, i) => (
<CarouselItem key={item.title.id} className="basis-auto pl-4">
<div key={item.title.id} className="shrink-0">
<div
className="animate-stagger-item"
style={{ "--stagger-index": i } as React.CSSProperties}
>
<ContinueWatchingCard item={item} />
</div>
</CarouselItem>
</div>
))}
</CarouselContent>
</Carousel>
</div>
</ScrollArea>
);
}
@@ -1,4 +1,4 @@
import { IconSparkles } from "@tabler/icons-react";
import { IconThumbUp } from "@tabler/icons-react";
import { getRecommendationsFeed } from "@/lib/services/discovery";
import { tmdbImageUrl } from "@/lib/tmdb/image";
import { FeedSection } from "./feed-section";
@@ -24,7 +24,7 @@ export async function RecommendationsSection({ userId }: { userId: string }) {
return (
<FeedSection
title="Recommended for You"
icon={<IconSparkles className="size-5 text-primary" />}
icon={<IconThumbUp className="size-5 text-primary" />}
>
<TitleGrid items={items} />
</FeedSection>