Animation

Animation

CSS keyframes나 선택한 JavaScript 애니메이션 라이브러리로 Radix Primitives를 애니메이션하는 방법이에요.

출처: 문서

본문

Radix Primitives에 애니메이션을 추가하는 것은 다른 컴포넌트와 비슷하지만, JS 애니메이션 라이브러리로 퇴장(exit) 애니메이션을 다룰 때 몇 가지 주의할 점이 있어요.

CSS 애니메이션으로 애니메이션하기

Primitives를 애니메이션하는 가장 간단한 방법은 CSS예요.

CSS animation으로 마운트(mount)와 언마운트(unmount) 두 단계를 모두 애니메이션할 수 있어요. 후자가 가능한 이유는 Radix Primitives가 애니메이션이 재생되는 동안 언마운트를 보류(suspend)하기 때문이에요.

@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes fadeOut {
  from {
    opacity: 1;
  }

  to {
    opacity: 0;
  }
}

.DialogOverlay[data-state="open"],
.DialogContent[data-state="open"] {
  animation: fadeIn 300ms ease-out;
}

.DialogOverlay[data-state="closed"],
.DialogContent[data-state="closed"] {
  animation: fadeOut 300ms ease-in;
}

JavaScript 애니메이션을 위한 언마운트 위임

많은 상태ful Primitive는 화면에서 숨겨지면 실제로 React 트리에서 제거되고 DOM에서도 요소가 제거돼요. JavaScript 애니메이션 라이브러리는 언마운트 단계를 제어해야 하므로, 많은 컴포넌트에 forceMount prop을 제공해 해당 라이브러리가 결정한 애니메이션 상태에 따라 children의 마운트/언마운트를 위임할 수 있게 해요.

예를 들어 React Spring으로 Dialog를 애니메이션하려면, useTransition 같은 훅의 애니메이션 상태를 기준으로 다이얼로그 Overlay와 Content 파트를 조건부 렌더링하면 돼요:

import { Dialog } from "radix-ui";

import { useTransition, animated, config } from "react-spring";

function Example() {
  const [open, setOpen] = React.useState(false);

  const transitions = useTransition(open, {
    from: { opacity: 0, y: -10 },

    enter: { opacity: 1, y: 0 },

    leave: { opacity: 0, y: 10 },

    config: config.stiff,
  });

  return (
    <Dialog.Root open={open} onOpenChange={setOpen}>
      <Dialog.Trigger>Open Dialog</Dialog.Trigger>

      {transitions((styles, item) =>
        item ? (
          <>
            <Dialog.Overlay forceMount asChild>
              <animated.div
                style={{
                  opacity: styles.opacity,
                }}
              />
            </Dialog.Overlay>

            <Dialog.Content forceMount asChild>
              <animated.div style={styles}>
                <h1>Hello from inside the Dialog!</h1>

                <Dialog.Close>close</Dialog.Close>
              </animated.div>
            </Dialog.Content>
          </>
        ) : null,
      )}
    </Dialog.Root>
  );
}

더 알아보기 (Learn more)

  • CSS 애니메이션은 마운트/언마운트 양쪽을 모두 처리할 수 있어요(Radix가 애니메이션 재생 중 언마운트 보류).
  • JS 애니메이션 라이브러리로 퇴장 애니메이션을 원하면 forceMount prop으로 마운트/언마운트를 직접 제어해야 해요.