Skip to content

Commit

Permalink
feat: carousel v2 transition animation
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnsonMao committed Aug 4, 2024
1 parent 7174602 commit 0eaa93c
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 39 deletions.
59 changes: 39 additions & 20 deletions components/shared/Carousel/v2/Carousel.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { FC, useState } from "react";
import { CSSProperties, FC, useEffect, useRef, useState } from "react";
import Icon from "../../Icon/v2/Icon";
import { cn } from "@/lib/utils";

interface CarouselProps<
T extends Record<string, unknown>,
K extends keyof T = keyof T,
Item extends Record<string, unknown>,
Key extends keyof Item = keyof Item,
> {
items: (T & Record<K, string>)[];
uniqueKey: K;
Component: FC<T>;
items: (Item & Record<Key, string>)[];
uniqueKey: Key;
Component: FC<Item>;
}

export default function Carousel<T extends Record<string, unknown>>({
export default function Carousel<Item extends Record<string, unknown>>({
items,
uniqueKey,
Component,
}: Readonly<CarouselProps<T>>) {
}: Readonly<CarouselProps<Item>>) {
const [showIndex, setShowIndex] = useState(0);
const [maxWidth, setMaxWidth] = useState(0);
const carouselRef = useRef<HTMLDivElement>(null);

const handleChangePage = (action: "prev" | "next") => () => {
const maxIndex = items.length - 1;
Expand All @@ -42,6 +43,10 @@ export default function Carousel<T extends Record<string, unknown>>({
"p-2.5 shrink-0 bg-white/4 shadow-default rounded-2xl";
const buttonIconClassName = "stroke-white w-6 h-6 pointer-events-none";

useEffect(() => {
setMaxWidth(carouselRef.current?.clientWidth || 0);
}, []);

return (
<div className="flex items-center">
<button
Expand All @@ -51,17 +56,31 @@ export default function Carousel<T extends Record<string, unknown>>({
>
<Icon name="navArrowLeft" className={buttonIconClassName} />
</button>
<ul>
{Array.isArray(items) &&
items.map((item, index) => (
<li
key={item[uniqueKey]}
className={cn(showIndex !== index && "hidden")}
>
<Component {...item} />
</li>
))}
</ul>
<div ref={carouselRef} className="overflow-hidden w-full">
<ul
className="flex transition-transform translate-x-[var(--translate-x)]"
style={
{
"--translate-x": `${showIndex * maxWidth * -1}px`,
} as CSSProperties
}
>
{Array.isArray(items) &&
items.map((item) => (
<li
key={item[uniqueKey]}
className="shrink-0 w-[var(--max-width)]"
style={
{
"--max-width": `${maxWidth}px`,
} as CSSProperties
}
>
<Component {...item} />
</li>
))}
</ul>
</div>
<button
type="button"
className={buttonClassName}
Expand Down
26 changes: 7 additions & 19 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,19 @@ import { useTranslation } from "next-i18next";

import Button from "@/components/shared/Button";
import CreateRoomModal from "@/components/lobby/CreateRoomModal";
import Carousel, { mockCarouselItems } from "@/components/shared/Carousel";
import { mockCarouselItems } from "@/components/shared/Carousel";
import CarouselV2 from "@/components/shared/Carousel/v2";
import FastJoinButton from "@/components/lobby/FastJoinButton";
import SearchBar from "@/components/shared/SearchBar";

function CarouselCard({ imgUrl, imgAlt }: (typeof mockCarouselItems)[number]) {
function CarouselCard({
imgUrl,
imgAlt,
}: Readonly<(typeof mockCarouselItems)[number]>) {
return (
<div className="flex text-white px-10 gap-4">
<div className="flex text-white px-12 gap-4">
<div className="relative flex-[60%]">
<Image
src={imgUrl}
alt={imgAlt ? imgAlt : ""}
draggable={false}
priority
fill
/>
<Image src={imgUrl} alt={imgAlt} draggable={false} priority fill />
</div>
<div className="flex-[40%] p-4 rounded-lg bg-primary-50/8">
<div className="text-xs">Massive Monster</div>
Expand Down Expand Up @@ -84,15 +81,6 @@ export default function Home() {
Component={CarouselCard}
/>
</div>
<div className="mt-[12px] mb-[22px]">
<Carousel
itemWidth={332}
itemHeight={158}
items={mockCarouselItems}
itemsToSlide={2}
autoplay
/>
</div>
<CreateRoomModal />
<Button component={Link} href="/rooms">
{t("rooms_list")}
Expand Down

0 comments on commit 0eaa93c

Please sign in to comment.