tailwindlabs / headlessui

Completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
https://headlessui.com
MIT License
25.02k stars 1.03k forks source link

Add new data-attribute-based transition API #3273

Closed RobinMalfait closed 3 weeks ago

RobinMalfait commented 3 weeks ago

We renamed the properties, see: https://github.com/tailwindlabs/headlessui/pull/3285


This PR adds a new way of dealing with transitions. Instead of using the <Transition /> component and using the enter, enterFrom, enterTo, leave, leaveFrom and leaveTo props, we can now define all of that in CSS.

Most components that are rendered conditionally based on the state of the component:

Will now accept a transition prop. The moment that is enabled then we will expose data-from, data-enter, data-exit and data-transition data attributes at the correct time. You can use these data attributes in your CSS or Tailwind Classes to style these components.

The lifecycle of the data attributes look like this:

┌─────┐              │       ┌────────────┐
│From │              │       │From        │
└─────┘              │       └────────────┘
┌─────┐┌─────┐┌─────┐│┌─────┐┌─────┐┌─────┐
│Frame││Frame││Frame│││Frame││Frame││Frame│
└─────┘└─────┘└─────┘│└─────┘└─────┘└─────┘
┌───────────────────┐│┌───────────────────┐
│Enter              │││Exit               │
└───────────────────┘│└───────────────────┘
┌───────────────────┐│┌───────────────────┐
│Transition         │││Transition         │
├───────────────────┘│└───────────────────┘
│
└─ Applied when `Enter` or `Exit` is applied.

The data-from attribute is applied at different times depending on the enter or exit transition. The styles applied using data-from are for describing the from state or the initial state.

For example, let's say you want to fade in the MenuItems, previously you would use the <Transition /> component for that:

<Transition
  enter="transition duration-200 ease-out"
  enterFrom="opacity-0"
  enterTo="opacity-100"
  leave="transition duration-200 ease-out"
  leaveFrom="opacity-100"
  leaveTo="opacity-0"
>
  <MenuItems />
</Transition>

There are a few things you might notice:

  1. The enterFrom and leaveTo are the same
  2. The enterTo and leaveFrom are the same
  3. The enterTo and leaveFrom are the default state of an element
  4. The enter and leave are the same

To use the data attribute approach, you can represent this like:

<MenuItems transition className="transition duration-200 ease-out data-[from]:opacity-0" />

The transition duration-200 ease-out were the same, so we can always define them.

The data-from data attribute represents the initial state, so we can define it once and it will be applied at the correct time.

If the duration or easing function is different depending on whether we are entering or exiting, then we can do that explicitly as well:

Before:

<Transition
  enter="transition duration-200 ease-out"
  enterFrom="opacity-0"
  enterTo="opacity-100"
  leave="transition duration-75 ease-in"
  leaveFrom="opacity-100"
  leaveTo="opacity-0"
>
  <MenuItems />
</Transition>

After:

<MenuItems
  transition
  className="transition data-[from]:opacity-0 data-[enter]:duration-200 data-[exit]:duration-75 data-[enter]:ease-out data-[exit]:ease-in"
/>

If the enter and leave states are different, e.g.: when entering from the left, and exiting to the right. Then we can combine the data attributes:

<Transition
  enter="transition duration-200 ease-out"
  enterFrom="-translate-x-full"
  enterTo="translate-x-0"
  leave="transition duration-200 ease-out"
  leaveFrom="translate-x-0"
  leaveTo="translate-x-full"
>
  <MenuItems />
</Transition>

After:

<MenuItems
  transition
  className={clsx([
    // Defaults
    'transition duration-200 ease-out',

    // Enter specific
    'data-[enter]:data-[from]:-translate-x-full',

    // Exit specific
    'data-[exit]:data-[from]:translate-x-full',
  ])}
/>

Notice that we didn't specify the translate-x-0 case because that's again the default state of an element.


The existing <Transition> and <TransitionChild> will also expose these data attributes to the underlying DOM node so that you can use them in your CSS for components or elements that don't have a transition prop.

vercel[bot] commented 3 weeks ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
headlessui-react ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 7, 2024 9:31am
headlessui-vue ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 7, 2024 9:31am