Skip to content

Commit deb558d

Browse files
committed
fix: soften todo sheet view transitions
1 parent ecacd03 commit deb558d

3 files changed

Lines changed: 32 additions & 27 deletions

File tree

src/feature/todo/todoBottomSheet/TodoBottomSheet.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const TodoBottomSheetWrapper = ({ isOpen, onOpen, children }: TodoBottomSheetWra
3737

3838
return (
3939
<>
40-
<BottomSheet isOpen={isOpen} showSheet={onOpen} closeSheet={handleCloseSheet} height="auto" animateHeight={false}>
40+
<BottomSheet isOpen={isOpen} showSheet={onOpen} closeSheet={handleCloseSheet}>
4141
{children}
4242
</BottomSheet>
4343

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import { AnimatePresence, motion, useReducedMotion } from 'framer-motion';
34
import { cn } from '@/shared/lib/utils';
45

56
interface StackViewProps {
@@ -13,12 +14,29 @@ interface StackViewProps {
1314

1415
/**
1516
* 스택 뷰 컴포넌트
16-
* 바텀시트 내부 화면을 즉시 전환합니다.
17+
* 바텀시트 위치를 유지하며 짧은 크로스페이드로 내부 화면을 전환합니다.
1718
*/
18-
export const StackView = ({ viewKey, children, className }: StackViewProps) => (
19-
<div data-view={viewKey} className={cn('h-full transform-none transition-none animate-none', className)}>
20-
{children}
21-
</div>
22-
);
19+
export const StackView = ({ viewKey, children, className }: StackViewProps) => {
20+
const shouldReduceMotion = useReducedMotion();
21+
const duration = shouldReduceMotion ? 0 : 0.15;
22+
23+
return (
24+
<div className={cn('relative h-full overflow-hidden', className)}>
25+
<AnimatePresence initial={false}>
26+
<motion.div
27+
key={viewKey}
28+
data-view={viewKey}
29+
initial={{ opacity: 0 }}
30+
animate={{ opacity: 1 }}
31+
exit={{ opacity: 0 }}
32+
transition={{ duration, ease: 'easeOut' }}
33+
className="absolute inset-0 flex h-full flex-col"
34+
>
35+
{children}
36+
</motion.div>
37+
</AnimatePresence>
38+
</div>
39+
);
40+
};
2341

2442
export default StackView;

src/shared/components/feedBack/BottomSheet.tsx

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -218,21 +218,15 @@ const BottomSheetProvider = ({
218218
};
219219

220220
// Root 컴포넌트 (오버레이 + 시트 컨테이너)
221-
const BottomSheetRoot = ({ children, animateHeight }: { children: React.ReactNode; animateHeight: boolean }) => {
221+
const BottomSheetRoot = ({ children }: { children: React.ReactNode }) => {
222222
const { isOpen, closeSheet, springHeight, snapPoints, heightMode, contentHeight, autoSpringHeight } =
223223
useBottomSheetContext();
224224

225225
const isAutoHeight = heightMode === 'auto';
226226
const isMeasured = contentHeight > 0;
227227

228-
// auto 모드: 측정 전에는 'auto', 측정 후에는 설정에 따라 즉시 또는 스프링으로 높이 반영
229-
const resolvedHeight = isAutoHeight
230-
? isMeasured
231-
? animateHeight
232-
? autoSpringHeight
233-
: contentHeight
234-
: 'auto'
235-
: springHeight;
228+
// auto 모드: 측정 전에는 'auto', 측정 후에는 스프링 애니메이션 적용
229+
const resolvedHeight = isAutoHeight ? (isMeasured ? autoSpringHeight : 'auto') : springHeight;
236230

237231
return (
238232
<AnimatePresence>
@@ -260,13 +254,9 @@ const BottomSheetRoot = ({ children, animateHeight }: { children: React.ReactNod
260254
overflow: 'hidden',
261255
paddingBottom: 'env(safe-area-inset-bottom)',
262256
}}
263-
initial={animateHeight ? { height: 0 } : false}
264-
animate={
265-
animateHeight
266-
? { height: isAutoHeight ? (isMeasured ? contentHeight : 'auto') : snapPoints.half }
267-
: undefined
268-
}
269-
exit={animateHeight ? { height: 0 } : undefined}
257+
initial={{ height: 0 }}
258+
animate={{ height: isAutoHeight ? (isMeasured ? contentHeight : 'auto') : snapPoints.half }}
259+
exit={{ height: 0 }}
270260
className={`fixed bottom-0 left-1/2 -translate-x-1/2 bg-bg-elevated max-w-md w-full rounded-t-lg ${Z_INDEX.SHEET}`}
271261
>
272262
<AutoHeightContent>{children}</AutoHeightContent>
@@ -369,20 +359,17 @@ export const BottomSheet = ({
369359
showSheet,
370360
closeSheet,
371361
height,
372-
animateHeight = true,
373362
}: {
374363
children: React.ReactNode;
375364
isOpen: boolean;
376365
showSheet: () => void;
377366
closeSheet: () => void;
378367
/** 높이 설정: 'auto' | '{x}px' | '{x}%' (기본값: '55%') */
379368
height?: BottomSheetHeight;
380-
/** 열림 및 콘텐츠 높이 변경 시 높이 애니메이션 적용 여부 */
381-
animateHeight?: boolean;
382369
}) => {
383370
return (
384371
<BottomSheetProvider isOpen={isOpen} showSheet={showSheet} closeSheet={closeSheet} heightMode={height}>
385-
<BottomSheetRoot animateHeight={animateHeight}>{children}</BottomSheetRoot>
372+
<BottomSheetRoot>{children}</BottomSheetRoot>
386373
</BottomSheetProvider>
387374
);
388375
};

0 commit comments

Comments
 (0)