Repository: tailwindlabs/headlessui
Pull request #3285 (2024-06-12 11:47:31)

Rename `data-from` -> `data-closed` and `data-exit` -> `data-leave`
This PR updates the newly exposed data attributes introduced in #3273

After playing with them in real projects, we improved the naming for a few reasons:

1. If you are describing the "from" state and if it's different for `enter` and `exit` then you would have to type:

   ```html
   <div
     class="data-[enter]:data-[from]:-translate-x-full data-[exit]:data-[from]:-translate-x-full"
   ></div>
   ```

   And `data-[exit]:data-[from]` reads like you are transitioning from a certain state, but you are transitioning _to_ that state.

2. If you use `leave` instead of `exit` then it will be consistent with the properties that we already have on the `Transition` component. Additionally, the length is the same now so they align better.

   ```jsx
   <div
     className={clsx(
       "data-[enter]:data-[closed]:-transition-x-full",
       "data-[exit]:data-[closed]:transition-x-full",
     )}
   />
   ```

   vs

   ```jsx
   <div
     className={clsx(
       "data-[enter]:data-[closed]:-transition-x-full",
       "data-[leave]:data-[closed]:transition-x-full",
     )}
   />
   ```


vercel[bot]: [vc]: #p0h9rriM+8NrCPEAvstOGHpLnSPtVlpap4Tv9jlpX1U=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJoZWFkbGVzc3VpLXJlYWN0Iiwicm9vdERpcmVjdG9yeSI6InBsYXlncm91bmRzL3JlYWN0IiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3RhaWx3aW5kbGFicy9oZWFkbGVzc3VpLXJlYWN0LzI2UzdHaHRadVhpZ2hkS1F0S2NvRFFCNHZYbnIiLCJwcmV2aWV3VXJsIjoiaGVhZGxlc3N1aS1yZWFjdC1naXQtZmVhdC1jaGFuZ2UtZGF0YS1hdHRyaS1jM2JlYTQtdGFpbHdpbmRsYWJzLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiUEVORElORyIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJoZWFkbGVzc3VpLXJlYWN0LWdpdC1mZWF0LWNoYW5nZS1kYXRhLWF0dHJpLWMzYmVhNC10YWlsd2luZGxhYnMudmVyY2VsLmFwcCJ9fV19
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **headlessui-react** | 🔄 Building ([Inspect](https://vercel.com/tailwindlabs/headlessui-react/26S7GhtZuXighdKQtKcoDQB4vXnr)) | [Visit Preview](https://vercel.live/open-feedback/headlessui-react-git-feat-change-data-attri-c3bea4-tailwindlabs.vercel.app?via=pr-comment-visit-preview-link&passThrough=1) | 💬 [**Add feedback**](https://vercel.live/open-feedback/headlessui-react-git-feat-change-data-attri-c3bea4-tailwindlabs.vercel.app?via=pr-comment-feedback-link) | Jun 12, 2024 11:47am |



Patch:
diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md
index bcfe314..6961276 100644
--- a/packages/@headlessui-react/CHANGELOG.md
+++ b/packages/@headlessui-react/CHANGELOG.md
@@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Added
 
 - Add ability to render multiple `<Dialog />` components at once (without nesting them) ([#3242](https://github.com/tailwindlabs/headlessui/pull/3242))
-- Add CSS based transitions using `data-*` attributes ([#3273](https://github.com/tailwindlabs/headlessui/pull/3273))
+- Add CSS based transitions using `data-*` attributes ([#3273](https://github.com/tailwindlabs/headlessui/pull/3273), [#3285](https://github.com/tailwindlabs/headlessui/pull/3285))
 
 ### Fixed
 
diff --git a/packages/@headlessui-react/src/hooks/use-transition-data.ts b/packages/@headlessui-react/src/hooks/use-transition-data.ts
index 64645d4..8e93692 100644
--- a/packages/@headlessui-react/src/hooks/use-transition-data.ts
+++ b/packages/@headlessui-react/src/hooks/use-transition-data.ts
@@ -7,35 +7,35 @@ import { useIsoMorphicEffect } from './use-iso-morphic-effect'
 
 /**
  * ```
- * ┌─────┐              │       ┌────────────┐
- * │From │              │       │From        │
- * └─────┘              │       └────────────┘
- * ┌─────┐┌─────┐┌─────┐│┌─────┐┌─────┐┌─────┐
- * │Frame││Frame││Frame│││Frame││Frame││Frame│
- * └─────┘└─────┘└─────┘│└─────┘└─────┘└─────┘
- * ┌───────────────────┐│┌───────────────────┐
- * │Enter              │││Exit               │
- * └───────────────────┘│└───────────────────┘
- * ┌───────────────────┐│┌───────────────────┐
- * │Transition         │││Transition         │
- * ├───────────────────┘│└───────────────────┘
+ * ┌──────┐                │        ┌──────────────┐
+ * │Closed│                │        │Closed        │
+ * └──────┘                │        └──────────────┘
+ * ┌──────┐┌──────┐┌──────┐│┌──────┐┌──────┐┌──────┐
+ * │Frame ││Frame ││Frame │││Frame ││Frame ││Frame │
+ * └──────┘└──────┘└──────┘│└──────┘└──────┘└──────┘
+ * ┌──────────────────────┐│┌──────────────────────┐
+ * │Enter                 │││Leave                 │
+ * └──────────────────────┘│└──────────────────────┘
+ * ┌──────────────────────┐│┌──────────────────────┐
+ * │Transition            │││Transition            │
+ * ├──────────────────────┘│└──────────────────────┘
  * │
- * └─ Applied when `Enter` or `Exit` is applied.
+ * └─ Applied when `Enter` or `Leave` is applied.
  * ```
  */
 enum TransitionState {
   None = 0,
 
-  From = 1 << 0,
+  Closed = 1 << 0,
 
   Enter = 1 << 1,
-  Exit = 1 << 2,
+  Leave = 1 << 2,
 }
 
 export type TransitionData = {
-  from?: boolean
+  closed?: boolean
   enter?: boolean
-  exit?: boolean
+  leave?: boolean
   transition?: boolean
 }
 
@@ -47,7 +47,7 @@ export function useTransitionData(
   let [visible, setVisible] = useState(show)
 
   let { hasFlag, addFlag, removeFlag } = useFlags(
-    visible ? TransitionState.From : TransitionState.None
+    visible ? TransitionState.Closed : TransitionState.None
   )
   let inFlight = useRef(false)
   let cancelledRef = useRef(false)
@@ -66,7 +66,7 @@ export function useTransitionData(
       if (!node) {
         // Retry if the DOM node isn't available yet
         if (show) {
-          addFlag(TransitionState.Enter | TransitionState.From)
+          addFlag(TransitionState.Enter | TransitionState.Closed)
           return d.nextFrame(() => retry())
         }
         return
@@ -89,10 +89,10 @@ export function useTransitionData(
           if (cancelledRef.current) return
 
           if (show) {
-            addFlag(TransitionState.Enter | TransitionState.From)
-            removeFlag(TransitionState.Exit)
+            addFlag(TransitionState.Enter | TransitionState.Closed)
+            removeFlag(TransitionState.Leave)
           } else {
-            addFlag(TransitionState.Exit)
+            addFlag(TransitionState.Leave)
             removeFlag(TransitionState.Enter)
           }
         },
@@ -103,23 +103,23 @@ export function useTransitionData(
             // new state.
             //
             // What we actually want is to revert to the "idle" state (the
-            // stable state where an `Enter` transitions to, and an `Exit`
+            // stable state where an `Enter` transitions to, and a `Leave`
             // transitions from.)
             //
             // Because of this, it might look like we are swapping the flags in
             // the following branches, but that's not the case.
             if (show) {
-              removeFlag(TransitionState.Enter | TransitionState.From)
-              addFlag(TransitionState.Exit)
+              removeFlag(TransitionState.Enter | TransitionState.Closed)
+              addFlag(TransitionState.Leave)
             } else {
-              removeFlag(TransitionState.Exit)
-              addFlag(TransitionState.Enter | TransitionState.From)
+              removeFlag(TransitionState.Leave)
+              addFlag(TransitionState.Enter | TransitionState.Closed)
             }
           } else {
             if (show) {
-              removeFlag(TransitionState.From)
+              removeFlag(TransitionState.Closed)
             } else {
-              addFlag(TransitionState.From)
+              addFlag(TransitionState.Closed)
             }
           }
         },
@@ -132,7 +132,7 @@ export function useTransitionData(
 
           inFlight.current = false
 
-          removeFlag(TransitionState.Enter | TransitionState.Exit | TransitionState.From)
+          removeFlag(TransitionState.Enter | TransitionState.Leave | TransitionState.Closed)
 
           if (!show) {
             setVisible(false)
@@ -147,9 +147,9 @@ export function useTransitionData(
     return [
       show,
       {
-        from: undefined,
+        closed: undefined,
         enter: undefined,
-        exit: undefined,
+        leave: undefined,
         transition: undefined,
       },
     ] as const
@@ -158,10 +158,10 @@ export function useTransitionData(
   return [
     visible,
     {
-      from: hasFlag(TransitionState.From),
+      closed: hasFlag(TransitionState.Closed),
       enter: hasFlag(TransitionState.Enter),
-      exit: hasFlag(TransitionState.Exit),
-      transition: hasFlag(TransitionState.Enter) || hasFlag(TransitionState.Exit),
+      leave: hasFlag(TransitionState.Leave),
+      transition: hasFlag(TransitionState.Enter) || hasFlag(TransitionState.Leave),
     },
   ] as const
 }


Test patch:
diff --git a/packages/@headlessui-react/src/components/transition/__snapshots__/transition.test.tsx.snap b/packages/@headlessui-react/src/components/transition/__snapshots__/transition.test.tsx.snap
index f133165..df81926 100644
--- a/packages/@headlessui-react/src/components/transition/__snapshots__/transition.test.tsx.snap
+++ b/packages/@headlessui-react/src/components/transition/__snapshots__/transition.test.tsx.snap
@@ -5,25 +5,25 @@ exports[`Setup API nested should be possible to change the underlying DOM tag of
   class="My Page"
 >
   <article
+    data-closed=""
     data-enter=""
-    data-from=""
-    data-headlessui-state="from enter transition"
+    data-headlessui-state="closed enter transition"
     data-transition=""
     style=""
   >
     <aside
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
       style=""
     >
       Sidebar
     </aside>
     <section
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
       style=""
     >
@@ -38,25 +38,25 @@ exports[`Setup API nested should be possible to change the underlying DOM tag of
   class="My Page"
 >
   <div
+    data-closed=""
     data-enter=""
-    data-from=""
-    data-headlessui-state="from enter transition"
+    data-headlessui-state="closed enter transition"
     data-transition=""
     style=""
   >
     <aside
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
       style=""
     >
       Sidebar
     </aside>
     <section
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
       style=""
     >
@@ -71,25 +71,25 @@ exports[`Setup API nested should be possible to nest transition components 1`] =
   class="My Page"
 >
   <div
+    data-closed=""
     data-enter=""
-    data-from=""
-    data-headlessui-state="from enter transition"
+    data-headlessui-state="closed enter transition"
     data-transition=""
     style=""
   >
     <div
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
       style=""
     >
       Sidebar
     </div>
     <div
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
       style=""
     >
@@ -104,23 +104,23 @@ exports[`Setup API nested should be possible to use render props on the Transiti
   class="My Page"
 >
   <article
+    data-closed=""
     data-enter=""
-    data-from=""
-    data-headlessui-state="from enter transition"
+    data-headlessui-state="closed enter transition"
     data-transition=""
   >
     <aside
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
     >
       Sidebar
     </aside>
     <section
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
     >
       Content
@@ -134,24 +134,24 @@ exports[`Setup API nested should be possible to use render props on the Transiti
   class="My Page"
 >
   <div
+    data-closed=""
     data-enter=""
-    data-from=""
-    data-headlessui-state="from enter transition"
+    data-headlessui-state="closed enter transition"
     data-transition=""
     style=""
   >
     <aside
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
     >
       Sidebar
     </aside>
     <section
+      data-closed=""
       data-enter=""
-      data-from=""
-      data-headlessui-state="from enter transition"
+      data-headlessui-state="closed enter transition"
       data-transition=""
     >
       Content
@@ -168,9 +168,9 @@ exports[`Setup API nested should yell at us when we forgot to forward the ref on
 
 exports[`Setup API shallow should be possible to change the underlying DOM tag 1`] = `
 <span
+  data-closed=""
   data-enter=""
-  data-from=""
-  data-headlessui-state="from enter transition"
+  data-headlessui-state="closed enter transition"
   data-transition=""
   style=""
 >
@@ -180,9 +180,9 @@ exports[`Setup API shallow should be possible to change the underlying DOM tag 1
 
 exports[`Setup API shallow should be possible to use a render prop 1`] = `
 <span
+  data-closed=""
   data-enter=""
-  data-from=""
-  data-headlessui-state="from enter transition"
+  data-headlessui-state="closed enter transition"
   data-transition=""
 >
   Children
@@ -192,9 +192,9 @@ exports[`Setup API shallow should be possible to use a render prop 1`] = `
 exports[`Setup API shallow should passthrough all the props (that we do not use internally) 1`] = `
 <div
   class="text-blue-400"
+  data-closed=""
   data-enter=""
-  data-from=""
-  data-headlessui-state="from enter transition"
+  data-headlessui-state="closed enter transition"
   data-transition=""
   id="root"
   style=""
@@ -206,9 +206,9 @@ exports[`Setup API shallow should passthrough all the props (that we do not use
 exports[`Setup API shallow should passthrough all the props (that we do not use internally) even when using an \`as\` prop 1`] = `
 <a
   class="text-blue-400"
+  data-closed=""
   data-enter=""
-  data-from=""
-  data-headlessui-state="from enter transition"
+  data-headlessui-state="closed enter transition"
   data-transition=""
   href="/"
   style=""
@@ -219,9 +219,9 @@ exports[`Setup API shallow should passthrough all the props (that we do not use
 
 exports[`Setup API shallow should render another component if the \`as\` prop is used and its children by default 1`] = `
 <a
+  data-closed=""
   data-enter=""
-  data-from=""
-  data-headlessui-state="from enter transition"
+  data-headlessui-state="closed enter transition"
   data-transition=""
   style=""
 >
@@ -235,9 +235,9 @@ exports[`Setup API shallow should yell at us when we forget to forward the ref w
 
 exports[`Setup API transition classes should be possible to passthrough the transition classes 1`] = `
 <div
+  data-closed=""
   data-enter=""
-  data-from=""
-  data-headlessui-state="from enter transition"
+  data-headlessui-state="closed enter transition"
   data-transition=""
   style=""
 >
@@ -248,8 +248,8 @@ exports[`Setup API transition classes should be possible to passthrough the tran
 exports[`Setup API transition classes should be possible to passthrough the transition classes and immediately apply the enter transitions when appear is set to true 1`] = `
 <div
   class="enter enter-from"
-  data-from=""
-  data-headlessui-state="from"
+  data-closed=""
+  data-headlessui-state="closed"
   style=""
 >
   Children
diff --git a/packages/@headlessui-react/src/components/transition/transition.test.tsx b/packages/@headlessui-react/src/components/transition/transition.test.tsx
index 58ebb6f..4a2b2d0 100644
--- a/packages/@headlessui-react/src/components/transition/transition.test.tsx
+++ b/packages/@headlessui-react/src/components/transition/transition.test.tsx
@@ -358,9 +358,9 @@ describe('Setup API', () => {
           <div
             class="foo1
         foo2"
+            data-closed=""
             data-enter=""
-            data-from=""
-            data-headlessui-state="from enter transition"
+            data-headlessui-state="closed enter transition"
             data-transition=""
             style=""
           >
@@ -382,9 +382,9 @@ describe('Setup API', () => {
            <div
              class="foo1
          foo2 foo1 foo2 leave"
+             data-closed=""
              data-enter=""
-             data-from=""
-             data-headlessui-state="from enter transition"
+             data-headlessui-state="closed enter transition"
              data-transition=""
              style=""
            >