From 37f607b9a6d5fa9702d649c2377495045da8dd8a Mon Sep 17 00:00:00 2001 From: minjeoong Date: Sat, 25 Oct 2025 19:04:37 +0900 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20ios=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EB=8C=80=EC=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/bds-ui/src/components/carousel/carousel.css.ts | 3 +++ .../src/components/carousel/hooks/use-carousel-touch.ts | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/packages/bds-ui/src/components/carousel/carousel.css.ts b/packages/bds-ui/src/components/carousel/carousel.css.ts index 10325cd9..d28b5118 100644 --- a/packages/bds-ui/src/components/carousel/carousel.css.ts +++ b/packages/bds-ui/src/components/carousel/carousel.css.ts @@ -9,6 +9,8 @@ export const container = style({ height: '100%', overflowX: 'scroll', userSelect: 'none', + WebkitOverflowScrolling: 'touch', + touchAction: 'pan-x', }); export const slideContainer = style({ @@ -20,6 +22,7 @@ export const slideContainer = style({ gap: '1rem', userSelect: 'none', WebkitUserSelect: 'none', + touchAction: 'pan-x', }); export const slide = style({ diff --git a/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts b/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts index 12b48116..6e71b01c 100644 --- a/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts +++ b/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts @@ -28,6 +28,10 @@ export const useCarouselTouch = ({ /** 누를 때 시작 위치 저장 */ const handlePointerDown = useCallback( (e: PointerEvent) => { + if (e.pointerType === 'touch') { + e.preventDefault(); + } + setIsDragging(true); setStartX(e.clientX); setDragOffset(0); @@ -49,6 +53,11 @@ export const useCarouselTouch = ({ return; } + // iOS Safari에서 스크롤 방지 + if (e.pointerType === 'touch') { + e.preventDefault(); + } + const dragDiff = startX - e.clientX; const diff = Math.abs(dragDiff); From d45e8e9ec066a80c45f623300981913b5d96385f Mon Sep 17 00:00:00 2001 From: minjeoong Date: Sun, 26 Oct 2025 02:00:44 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EC=BA=90=EB=9F=AC=EC=85=80=20autoP?= =?UTF-8?q?lay=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EB=8C=80=EC=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/client/src/pages/home/home-page.tsx | 2 +- .../components/info-section/info-section.tsx | 2 +- .../src/components/carousel/carousel.tsx | 20 +++++++--- .../carousel/hooks/use-carousel-touch.ts | 39 +++++++++---------- 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/apps/client/src/pages/home/home-page.tsx b/apps/client/src/pages/home/home-page.tsx index 830c17b3..17cd32ff 100644 --- a/apps/client/src/pages/home/home-page.tsx +++ b/apps/client/src/pages/home/home-page.tsx @@ -43,7 +43,7 @@ const HomePage = () => { /> {userData?.isRecommendInsurance ? ( <> - + ) : ( diff --git a/apps/client/src/widgets/home/components/info-section/info-section.tsx b/apps/client/src/widgets/home/components/info-section/info-section.tsx index 7a6f6848..4c4f9f54 100644 --- a/apps/client/src/widgets/home/components/info-section/info-section.tsx +++ b/apps/client/src/widgets/home/components/info-section/info-section.tsx @@ -34,7 +34,7 @@ export const InfoSection = () => { {homeCardConfig.map((card, index) => ( - + 0 && containerWidth > 0) { const config: CarouselControllerConfig = { totalItems, - slidesPerView: 1, // 항상 1개씩 이동 + slidesPerView: 1, slideWidth: (autoSlideWidth / containerWidth) * 100, infinite: effectiveInfinite, }; @@ -370,8 +370,10 @@ const Carousel = ({ transform: getTransform(), transition: isDragging ? 'none' - : 'transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94)', - cursor: isDragging ? 'grabbing' : 'pointer', + : autoPlay + ? 'none' + : 'transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94)', + cursor: isDragging ? 'grabbing' : 'grab', height: maxSlideHeight ? `${maxSlideHeight}px` : 'auto', width: isAutoMode ? 'max-content' : '100%', }} @@ -380,13 +382,21 @@ const Carousel = ({ const itemProps = ( slide.data as React.ReactElement ).props; - const { children, className, ...restProps } = itemProps; + const { + children, + className, + style: itemStyle, + ...restProps + } = itemProps; return (
{children} diff --git a/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts b/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts index 6e71b01c..355a6d73 100644 --- a/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts +++ b/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts @@ -53,7 +53,6 @@ export const useCarouselTouch = ({ return; } - // iOS Safari에서 스크롤 방지 if (e.pointerType === 'touch') { e.preventDefault(); } @@ -74,7 +73,7 @@ export const useCarouselTouch = ({ /** 뗄 때 드래그 거리 기준으로 컨트롤러를 통해 새로운 상태 계산 * - autoPlay=false: 드래그 여부에 따라 슬라이드 변경 or 클릭 이벤트 처리 - * - autoPlay=true: 항상 드래그로 처리 (onClick 무시) + * - autoPlay=true: 드래그 후 RAF 재개를 위해 상태 업데이트 */ const handlePointerUp = useCallback( @@ -83,12 +82,24 @@ export const useCarouselTouch = ({ return; } - if (!autoPlay) { - if (hasMoved) { - const diff = startX - e.clientX; - const containerWidth = e.currentTarget.clientWidth || 1; - const dragOffsetPercent = (diff / containerWidth) * 100; + const diff = startX - e.clientX; + const containerWidth = e.currentTarget.clientWidth || 1; + const dragOffsetPercent = (diff / containerWidth) * 100; + + // autoPlay 모드에서는 드래그만 처리 + if (autoPlay) { + const newState = controller.handleDragEnd( + carouselState, + dragOffsetPercent, + { + isAutoPlay: true, + }, + ); + onStateUpdate(newState); + } else { + // 수동 모드에서는 드래그 vs 클릭 구분 + if (hasMoved) { const newState = controller.handleDragEnd( carouselState, dragOffsetPercent, @@ -103,20 +114,6 @@ export const useCarouselTouch = ({ clickTarget.click(); } } - } else { - const diff = startX - e.clientX; - const containerWidth = e.currentTarget.clientWidth || 1; - const dragOffsetPercent = (diff / containerWidth) * 100; - - const newState = controller.handleDragEnd( - carouselState, - dragOffsetPercent, - { - isAutoPlay: true, - }, - ); - - onStateUpdate(newState); } setIsDragging(false); From 27ff7c945b89d973ef3660d94604af2990c062eb Mon Sep 17 00:00:00 2001 From: minjeoong Date: Sun, 26 Oct 2025 02:30:58 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/client/src/pages/home/home-page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/pages/home/home-page.tsx b/apps/client/src/pages/home/home-page.tsx index 17cd32ff..830c17b3 100644 --- a/apps/client/src/pages/home/home-page.tsx +++ b/apps/client/src/pages/home/home-page.tsx @@ -43,7 +43,7 @@ const HomePage = () => { /> {userData?.isRecommendInsurance ? ( <> - + ) : ( From e928c3339f2c88328a53a0f88aeaa6532fe7a165 Mon Sep 17 00:00:00 2001 From: minjeoong Date: Sun, 26 Oct 2025 02:34:20 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/bds-ui/src/components/carousel/carousel.tsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/bds-ui/src/components/carousel/carousel.tsx b/packages/bds-ui/src/components/carousel/carousel.tsx index 9bce5eea..e7731fd4 100644 --- a/packages/bds-ui/src/components/carousel/carousel.tsx +++ b/packages/bds-ui/src/components/carousel/carousel.tsx @@ -382,21 +382,13 @@ const Carousel = ({ const itemProps = ( slide.data as React.ReactElement ).props; - const { - children, - className, - style: itemStyle, - ...restProps - } = itemProps; + const { children, className, ...restProps } = itemProps; return (
{children} From d6506bcd255056879927ab5a9b4100b143ed2d76 Mon Sep 17 00:00:00 2001 From: minjeoong Date: Sun, 26 Oct 2025 02:35:25 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bds-ui/src/components/carousel/hooks/use-carousel-touch.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts b/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts index 355a6d73..8c3c7a76 100644 --- a/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts +++ b/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts @@ -86,7 +86,6 @@ export const useCarouselTouch = ({ const containerWidth = e.currentTarget.clientWidth || 1; const dragOffsetPercent = (diff / containerWidth) * 100; - // autoPlay 모드에서는 드래그만 처리 if (autoPlay) { const newState = controller.handleDragEnd( carouselState, @@ -98,7 +97,6 @@ export const useCarouselTouch = ({ onStateUpdate(newState); } else { - // 수동 모드에서는 드래그 vs 클릭 구분 if (hasMoved) { const newState = controller.handleDragEnd( carouselState, From d1c4c862edc84ce07b405b727486d34b615f7bc8 Mon Sep 17 00:00:00 2001 From: minjeoong Date: Sun, 26 Oct 2025 02:39:02 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20jsdoc=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bds-ui/src/components/carousel/hooks/use-carousel-touch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts b/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts index 8c3c7a76..b082b16d 100644 --- a/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts +++ b/packages/bds-ui/src/components/carousel/hooks/use-carousel-touch.ts @@ -73,7 +73,7 @@ export const useCarouselTouch = ({ /** 뗄 때 드래그 거리 기준으로 컨트롤러를 통해 새로운 상태 계산 * - autoPlay=false: 드래그 여부에 따라 슬라이드 변경 or 클릭 이벤트 처리 - * - autoPlay=true: 드래그 후 RAF 재개를 위해 상태 업데이트 + * - autoPlay=true: 항상 드래그로 처리 (onClick 무시) */ const handlePointerUp = useCallback(