Headless UI v2.1: 간소화된 트랜지션 API 및 개선된 다중 다이얼로그 지원

Date
Headless UI v2.1

React용 Headless UI v2.1을 출시했습니다. 이번 버전에서는 트랜지션 API를 크게 간소화하고, 여러 다이얼로그를 형제 엘리먼트로 렌더링하는 기능을 추가했습니다.


간소화된 트랜지션 API

v2.1에서 트랜지션을 훨씬 쉽게 만들었습니다. 트랜지션을 적용할 수 있는 모든 내장 컴포넌트에 새로운 transition prop을 추가하고, 각 트랜지션 단계에 대한 데이터 속성(data attributes)을 추가했습니다. 이제 타겟 엘리먼트에 클래스를 추가하는 것만으로도 트랜지션 스타일을 적용할 수 있습니다:

import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'

function Example() {
  return (
    <Menu>
      <MenuButton>My account</MenuButton>
      <MenuItems
        transition
        className={`
          transition ease-out
          data-[closed]:scale-95 data-[closed]:opacity-0
          data-[enter]:duration-200 data-[leave]:duration-300
        `}
      >
        {/* 메뉴 아이템… */}
      </MenuItems>
    </Menu>
  )
}

트랜지션의 각 단계를 타겟팅하기 위해 사용할 수 있는 네 가지 데이터 속성이 있습니다:

  • data-closed: 엘리먼트가 진입할 때 시작하고, 떠날 때 도달해야 하는 스타일.
  • data-enter: 엘리먼트가 진입하는 동안 적용할 스타일. 예를 들어 지속 시간(duration)이나 이징 곡선(easing curve).
  • data-leave: 엘리먼트가 떠나는 동안 적용할 스타일. 예를 들어 지속 시간이나 이징 곡선.
  • data-transition: 엘리먼트가 진입하거나 떠날 때 적용할 스타일. 두 단계 간에 값을 공유할 때 유용.

이러한 속성을 중첩하여 진입과 떠날 때 서로 다른 closed 스타일을 사용할 수도 있습니다. 예를 들어, 이 다이얼로그는 왼쪽에서 슬라이드되지만 오른쪽으로 슬라이드됩니다:

import { Dialog } from '@headlessui/react'
import { useState } from 'react'

function Example() {
  let [isOpen, setIsOpen] = useState(false)

  return (
    <>
      <button onClick={() => setIsOpen(true)}>다이얼로그 열기</button>
      <Dialog
        open={isOpen}
        onClose={() => setIsOpen(false)}
        transition
        className={`
          transition ease-out duration-300
          data-[closed]:opacity-0
          data-[closed]:data-[enter]:-translate-x-8
          data-[closed]:data-[leave]:translate-x-8
        `}
      >
        {/* 다이얼로그 내용… */}
      </Dialog>
    </>
  )
}

일반 HTML 엘리먼트나 다른 컴포넌트를 트랜지션할 때는 여전히 <Transition> 컴포넌트를 사용할 수 있지만, 새로운 데이터 속성 API를 활용할 수 있습니다:

import { Transition } from '@headlessui/react'
import { useState } from 'react'

function Example() {
  const [isShowing, setIsShowing] = useState(false)

  return (
    <>
      <button onClick={() => setIsShowing((isShowing) => !isShowing)}>토글</button>
      <Transition show={isShowing}>
        <div className="transition duration-300 data-[closed]:opacity-0">
          페이드 인/아웃 효과
        </div>
      </Transition>
    </>
  )
}

이미 Tailwind UI의 모든 컴포넌트를 이 새로운 트랜지션 API로 업데이트했으며, 코드가 훨씬 간결하고 가벼워졌습니다. Modal Dialog, Dropdown, Slide-over, Flyout Menu, 또는 Select Menu 컴포넌트에서 더 많은 예제를 확인할 수 있습니다.

기존 API는 하위 호환성을 위해 계속 작동하지만, 앞으로는 이 새로운 접근 방식을 권장할 예정입니다.

업데이트된 Transition 컴포넌트 문서에서 더 자세히 알아보세요.


다중 다이얼로그를 형제로 렌더링하기

Headless UI v2.1에서는 이제 여러 다이얼로그를 서로 중첩하지 않고 동시에 렌더링할 수 있습니다.

이 기능은 애플리케이션의 두 개의 관련 없는 부분이 동시에 다이얼로그를 표시해야 할 때 매우 유용합니다. 예를 들어, 이미 어떤 종류의 확인 다이얼로그가 열려 있는 상태에서 다른 부분에서 네트워크 연결이 끊겼거나 세션이 만료되어 새로운 다이얼로그를 표시해야 하는 경우에 적합합니다.

최근에 작업 중인 애플리케이션 UI 키트인 Catalyst를 사용한 예시는 다음과 같습니다:

각 다이얼로그가 열린 순서를 추적하며, 가장 마지막에 열린 다이얼로그가 ESC 키를 누르거나 다이얼로그 외부를 클릭했을 때 닫히게 됩니다.


이 기능을 사용하려면 최신 버전의 Headless UI를 설치하세요:

$ npm i @headlessui/react@latest

문제가 발생하면 GitHub에서 알려주세요!