From e01a08a927ac001964ee9ec81e48a6dc70446b90 Mon Sep 17 00:00:00 2001 From: gwagjiug Date: Wed, 15 Jan 2025 21:53:39 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=AC=B4=ED=95=9C=20=EC=BA=90=EB=9F=AC?= =?UTF-8?q?=EC=85=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EC=97=90=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=8A=AC=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=93=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infinite-carousel.css.ts | 38 +++++- .../infinite-carousel.stories.tsx | 26 ++-- .../infinite-carousel/infinite-carousel.tsx | 122 +++++++++++++++--- 3 files changed, 149 insertions(+), 37 deletions(-) diff --git a/packages/design-system/src/components/infinite-carousel/infinite-carousel.css.ts b/packages/design-system/src/components/infinite-carousel/infinite-carousel.css.ts index 38936e0..1c499a0 100644 --- a/packages/design-system/src/components/infinite-carousel/infinite-carousel.css.ts +++ b/packages/design-system/src/components/infinite-carousel/infinite-carousel.css.ts @@ -4,15 +4,39 @@ import { style } from '@vanilla-extract/css'; export const wrap = style({ width: '33.5rem', height: '19.3rem', + overflow: 'hidden', + position: 'relative', +}); + +export const imageContainer = style({ + display: 'flex', + width: '100%', + height: '100%', + position: 'absolute', + transition: 'transform 1s ease-in-out', +}); + +export const image = style({ + width: '100%', + height: '100%', + objectFit: 'cover', + flexShrink: 0, +}); + +export const active = style({ + opacity: 1, }); export const container = style({ ...themeVars.display.flexCenter, - width: '33.5rem', - height: '19.3rem', + background: themeVars.color.black_op, + width: '100%', + height: '100%', flexShrink: '0', - padding: '1.6rem, 1.2rem', - backgroundColor: themeVars.color.black, + padding: '1.6rem 1.2rem', + position: 'absolute', + top: 0, + left: 0, }); export const info = style({ @@ -20,7 +44,6 @@ export const info = style({ width: '31.1rem', height: '16.1rem', alignItems: 'flex-start', - gap: '7.1rem', flexShrink: '0', }); @@ -35,16 +58,17 @@ export const infoDday = style({ ...themeVars.fontStyles.title1_b_24, }); -export const artist = style({ +export const subtitle = style({ ...themeVars.fontStyles.title3_b_18, color: themeVars.color.confeti_lime, }); -export const subtitle = style({ +export const fixedWord = style({ ...themeVars.fontStyles.title3_b_18, color: themeVars.color.white, }); export const infoBottom = style({ + marginTop: '9.8rem', ...themeVars.display.flexBetween, }); diff --git a/packages/design-system/src/components/infinite-carousel/infinite-carousel.stories.tsx b/packages/design-system/src/components/infinite-carousel/infinite-carousel.stories.tsx index 975110c..138ae66 100644 --- a/packages/design-system/src/components/infinite-carousel/infinite-carousel.stories.tsx +++ b/packages/design-system/src/components/infinite-carousel/infinite-carousel.stories.tsx @@ -1,9 +1,10 @@ -import type { Meta } from '@storybook/react'; +import { Meta } from '@storybook/react'; import InfiniteCarousel from './infinite-carousel'; +import { BANNER_DATA } from './mocks/bottom-banner-data'; -const meta: Meta = { +const meta: Meta = { title: 'Common/InfiniteCarousel', - component: InfiniteCarousel.Image, + component: InfiniteCarousel.Wrap, parameters: { layout: 'centered', }, @@ -11,13 +12,16 @@ const meta: Meta = { args: {}, }; +const bannerData = BANNER_DATA?.data?.performances || []; +const TotalIndexData = BANNER_DATA?.data?.performanceCount; + export default meta; -export const Default = () => ( - - - - - - -); +export const Default = () => { + return ( + + ); +}; diff --git a/packages/design-system/src/components/infinite-carousel/infinite-carousel.tsx b/packages/design-system/src/components/infinite-carousel/infinite-carousel.tsx index c2b6fda..ef06ff2 100644 --- a/packages/design-system/src/components/infinite-carousel/infinite-carousel.tsx +++ b/packages/design-system/src/components/infinite-carousel/infinite-carousel.tsx @@ -1,49 +1,133 @@ -import * as styles from './infinite-carousel.css'; +import { useEffect } from 'react'; import { ReactNode } from 'react'; -interface CarouselImageProps { +import * as styles from './infinite-carousel.css'; +import ProgressBar from './progress-bar/progress-bar'; +import { useCarouselData } from './hooks/use-carousel-data'; +import { useCarouselSlide } from './hooks/use-carousel-slide'; +import { useControlTime } from './hooks/use-control-time'; +interface CarouselWrapProps { + performances: { + reservationBgUrl: string; + subtitle: string; + reserveAt: string; + }[]; + indexData: number; +} + +interface CarouselContainerProps { children: React.ReactNode; } + interface CarouselInfoProps { children: ReactNode; - artist?: string; - subtitle?: string; } interface CarouselDdayProps { - day: string; + reserveAt: string; } interface CarouselArtistProps { - artist: string; - subtitle: string; + subtitle: string | undefined; } -const CarouselImage = ({ children }: CarouselImageProps) => ( -
-
{children}
-
+interface CarouselInfoBottomProps { + children: ReactNode; +} + +const CarouselWrap = ({ performances, indexData }: CarouselWrapProps) => { + // 슬라이드 데이터 + const copyImage = useCarouselData( + performances.map((item) => item.reservationBgUrl), + performances.map((item) => item.subtitle), + performances.map((item) => item.reserveAt), + ); + + // 슬라이드 상태 관리 + const { currentIndex, carouselTransition, nextSlide } = useCarouselSlide( + copyImage.images.length, + ); + + // 슬라이드 간격 관리 + const controlTime = useControlTime(carouselTransition); + + // 자동 슬라이드 전환 + useEffect(() => { + const interval = setInterval(nextSlide, controlTime); + return () => clearInterval(interval); + }, [nextSlide, controlTime]); + + return ( +
+
+ {copyImage.images.map((imgUrl, id) => ( + {`캐러셀 + ))} +
+ + + + + + + + + +
+ ); +}; + +const CarouselContainer = ({ children }: CarouselContainerProps) => ( +
{children}
); const CarouselInfo = ({ children }: CarouselInfoProps) => (
{children}
-
{children}
); -const CarouselDday = ({ day }: CarouselDdayProps) => ( -
D-{day}
+const CarouselInfoBottom = ({ children }: CarouselInfoBottomProps) => ( +
{children}
+); + +const CarouselDday = ({ reserveAt }: CarouselDdayProps) => ( +
D-{reserveAt}
); -const CarouselArtist = ({ artist, subtitle }: CarouselArtistProps) => ( -
- {artist} {subtitle} -
+const CarouselArtist = ({ subtitle }: CarouselArtistProps) => ( + <> + + {subtitle} 예매 + + ); const InfiniteCarousel = { - Image: CarouselImage, + Wrap: CarouselWrap, + Container: CarouselContainer, Info: CarouselInfo, + InfoBottom: CarouselInfoBottom, Dday: CarouselDday, Artist: CarouselArtist, };