요구사항 분석

  1. 메모 아이템을 클릭하면 메모 아이템이 Zoom-In 되는 듯한 애니메이션을 넣는다.

개발 과정

1. 바깥을 클릭하면 메모가 꺼진다

  1. useClickOutside 훅

    import { RefObject, useEffect } from 'react';
    
    interface UseClickOutsideProps {
      ref: RefObject<HTMLElement>;
      handler: () => void;
      enabled?: boolean;
    }
    
    export function useClickOutside({ ref, handler, enabled = true }: UseClickOutsideProps) {
      useEffect(() => {
        if (!enabled) return;
    
        const handleClickOutside = (event: MouseEvent) => {
          if (ref.current && !ref.current.contains(event.target as Node)) {
            handler();
          }
        };
    
        document.addEventListener('mousedown', handleClickOutside);
        return () => {
          document.removeEventListener('mousedown', handleClickOutside);
        };
      }, [ref, handler, enabled]);
    }
    
  2. 사용하는 측

    useClickOutside({
      ref: dialogRef,
      handler: closeDialog,
      enabled: open,
    });
    // ..
    <motion.div 
      layoutId={`card-container-${id}`} 
      ref={dialogRef}
      transition={{
        layout: { duration: 0.3, ease: "easeOut" }
      }}
    >
    

2. motion의 layout 속성을 활용한다.

여기서 중요한 것은, layoutId에 동일한 props를 전달하여 같은 요소라는 것을 motion에게 알려주는 것이다.

3. 자연스러운 애니메이션을 보여준다.

Before

화면 기록 2025-01-05 오후 4.15.45.mov

After

화면 기록 2025-01-05 오후 4.16.02.mov

막힌 점