Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Keep the dialog in the rendered tree until the leave animation reports completion. If you set open to false and also stop rendering the dialog in the same update, React removes its DOM immediately; there is then no element on which an exit animation can run.

The implementation depends on who owns presence: Radix can delay unmounting for recognized CSS keyframes, a JavaScript animation library can take over mounting with Radix’s forceMount, Motion can observe a removed direct child through AnimatePresence, and React’s current ViewTransition API can animate additions and removals inside a transition. A portal does not solve the problem by itself.

The lifecycle rule behind every working exit animation

An exit animation needs two phases: a visible phase while the dialog is open and a leave phase after closing begins. During the leave phase, the dialog (or the specific overlay and content nodes being animated) must still be mounted. Only after the animation completes should the presence owner remove those nodes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

This is different from the dialog’s logical state. The boolean open can become false immediately so application state, event handlers and accessibility logic know that closing has started. A separate presence value must remain true for the duration of the exit animation. When that value becomes false, the animation system may finally unmount the DOM.

#1 Best Overall
Sale
Compressed Air Duster,130000RPM Super Power Cordless Air Duster,Rechargeable Brushless Blower,3 Gear Adjustable Blower with LED Light,Dust Remover for Computer/House/Outdoor/Car
  • Powerful Turbo Fan:CAGIWIRU Electric Air Duster have reached speed up to 130000RPM,Can efficient remove dust and debris.With LED light and Three Adjustable Speed to meet with different cleaning tasks.
  • With Attached USB C Fasting Charging cable.Charing 3 hours,Enjoy up to 240 minutes of use on the lowest setting, For third speed can use for 25mins.with four charging options to meet with your needs.
  • Wide Application: attached 5 different nozzles,making it suitable for a variety of scenes, such as car,pet, pc, keyboards, and other electronic devices. It also serves for office and home clean duster.
  • Handy Design & Portable:Cordless air duster electric nozzle is Light weight and small size, design and comfortable to hold and space saving, convenient to carry around. You can put it in your room or inside the car without taking up space.
  • Economical &Reusable: Built durable materials with a long-lasting battery,our CAGIWIRU air duster it's a sustainable alternative to disposable air cans.

Think of the close as a small state machine rather than one boolean:

  1. Open: the trigger, overlay and content are mounted and displayed.
  2. Leaving: logical open is false, but the animated nodes remain mounted and receive their exit styles or animation values.
  3. Exited: the animation owner reports completion, so the nodes can be removed.

A common failure looks like this:

<Dialog.Root open={open} onOpenChange={setOpen}>
  {open && <Dialog.Content>...</Dialog.Content>}
</Dialog.Root>

The conditional expression removes Dialog.Content in the same render that changes open. No CSS keyframe, spring or tween can animate an element that no longer exists. Keep the conditional boundary at the level managed by your presence or animation library instead.

Separate logical close from physical removal

Do not delay the logical close merely to make the visual effect possible. Let the dialog’s open state change when the user activates Close, presses Escape, or another part of the application requests closure. The presence owner then represents the short period in which the UI is visually leaving. This separation prevents application code from treating a dialog as interactive after it has logically closed, while still giving the user a complete fade or slide-out.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Conversely, do not create a second timer that guesses when removal is safe if the animation library already reports completion. A hard-coded timer can drift from a changed duration, a reduced-motion rule, or a spring that settles at a different time. Use the lifecycle callback or presence value supplied by the owner of the animation.

Choose the presence owner before writing the close handler

There is no single React-specific switch that makes every dialog stay mounted. Select the owner that knows when the leave phase has finished:

Option Who controls removal? Best fit Main caveat
Radix CSS keyframes Radix presence behavior State-driven enter and exit animations written as CSS keyframes The documented mechanism concerns CSS animations; do not assume that an arbitrary CSS transition is held for you. See Radix’s animation guide.
Radix forceMount plus JavaScript animation The animation library’s presence state Spring or tween libraries that need an explicit leave phase Render the primitive parts while the leave item exists, then remove them after completion. Radix documents forceMount in its Dialog reference.
Motion AnimatePresence Motion observes removed direct children Applications already using Motion for enter and exit animations The boundary must remain mounted and directly observe the child that is conditionally removed. See Motion’s AnimatePresence documentation.
React ViewTransition React’s transition behavior Projects using the current documented React transition APIs Check the project’s React version and transition setup before relying on it. See the ViewTransition reference.

The practical question is “who receives the completion event?” If Radix recognizes the CSS animation, Radix owns removal. If a JavaScript library exposes a transition item or completion callback, that library owns removal. If Motion observes a direct child, the AnimatePresence boundary owns the exit lifecycle. This decision determines where your conditional expression belongs.

Radix Dialog with CSS keyframes

For a simple state-driven animation, Radix documents CSS as the simplest approach. Its presence behavior suspends unmounting while the primitive’s CSS animation plays. The animation guide shows both the open and closed states using data-state selectors on DialogOverlay and DialogContent: Animation | Radix Primitives.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Keep the Radix parts in the normal tree

Let Dialog.Root receive the open state and render the overlay and content normally. Do not add a second {open && ...} around those parts merely to save a render. Radix needs to see the state change and keep its presence wrapper alive for the CSS animation.

<Dialog.Root open={open} onOpenChange={setOpen}>
  <Dialog.Trigger>Open settings</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay className="DialogOverlay" />
    <Dialog.Content className="DialogContent">
      <Dialog.Title>Settings</Dialog.Title>
      <Dialog.Description>Update your preferences.</Dialog.Description>
      <Dialog.Close>Close</Dialog.Close>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

2. Define matching open and closed keyframes

Use the state attribute that Radix applies to each primitive. The following is the shape of the guide’s example; its 300 ms duration is an example value, not a measured recommendation.

Rank #2
EVEO® Screen Cleaner Spray Kit (Streak-Free) TV Screen Cleaner for Smart TV, Lcd, LEd, Oled | Computer Screen Cleaner Spray and Wipe Microfiber Cloth - TV, Monitor, Laptop, iPad, Car - 6.7oz 1 Pack
  • Screen Cleaner is Your Screen’s New Bestfriend! - EVEO is proud to present a screen cleaner that’s perfectly suited for your TV. Meet your new screen cleaner, computer screen cleaner, laptop cleaner, iPad cleaner, Macbook,tv cleaner or any other electronic device. Our screen cleaner spray and wipe along with the included plush microfiber cloth, easily removes dust, fingerprints & other smudges on the screen’s surface. Clean effectively for a streak-free screen
  • Gentle on your Screens - Our screen cleaner spray and wipes is compatible to be used even for the most sensitive LCD, LED, CRT, and OLED screens in proper use. Be at ease knowing that this product is compatible with all the major brands: LG, SONY, Samsung, Sharp, iPad, iPhone, Android screens, Kindle, PC monitors - we’ve got you covered! Can be used as LCD screen cleaner, tv cleaner, smart tv screen cleaner, and more
  • Premium Super Soft Plush Microfiber Cloth - Included in this efficient screen cleaning kit. This screen cleaner spray and wipe has our signature plush microfiber cloth specially designed to comply with screens and monitors and leave them streak-free. Has been shown to effectively absorbs stubborn stains, zero streaks, and no fiber shedding. Always use this together with our screen cleaner for the best results
  • Easy-to-Use Screen Cleaner Kit + microfiber cleaning cloth - The EVEO Screen Cleaning Kit will easily be your new favorite tool when it comes to taking care of the things you love most, quick and easy solution for a streak-free screen. Simply screw on the sprayer gun on the screen cleaner bottle. Spray the cleaning liquid onto the microfiber cloth, then wipe the screen until desired cleanliness & shine is achieved.
  • Quality Screen Care Kit Worth Purchasing - Enjoy a convenient Screen Cleaner anytime, anywhere you need it. Your satisfaction is our top priority. We stand behind the quality of our products and that’s why, you shouldn’t be worrying at all. We manufacture the Best Screen Cleaner. and can be used for laptop cleaning kit, laptop screen cleaner, tv screen cleaner for smart tv. MacBook screen cleaner, monitor cleaner or screen cleaner spray for electronic devices with microfiber cleaning cloth
.DialogOverlay[data-state='open'] {
  animation: overlayShow 300ms ease-out;
}
.DialogOverlay[data-state='closed'] {
  animation: overlayHide 300ms ease-in;
}
.DialogContent[data-state='open'] {
  animation: contentShow 300ms ease-out;
}
.DialogContent[data-state='closed'] {
  animation: contentHide 300ms ease-in;
}

@keyframes overlayShow {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes overlayHide {
  from { opacity: 1; }
  to { opacity: 0; }
}
@keyframes contentShow {
  from { opacity: 0; transform: translateY(8px) scale(.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes contentHide {
  from { opacity: 1; transform: translateY(0) scale(1); }
  to { opacity: 0; transform: translateY(8px) scale(.98); }
}

The important detail is not the easing or distance; it is that the closed keyframe is attached to the element while it is still mounted. Radix can then delay unmounting until that CSS animation finishes.

What this method does not promise

The documented Radix mechanism is based on CSS animations. Do not generalize it to every CSS transition, a manually toggled class with no animation event, or a custom timer that Radix cannot observe. If your effect is controlled by JavaScript, use the delegated-presence pattern below.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Also make sure both the overlay and content receive a closed animation if both should fade or move. A closed selector on only one primitive cannot keep the other primitive visually present. If the two durations differ, the presence decision still needs to account for the part that should remain longest; otherwise one node can disappear while the other is finishing.

Radix Dialog with a JavaScript animation library

Spring and tween libraries usually need to own the leave timeline. Radix explicitly provides forceMount for this case: “JavaScript animation libraries need control of the unmounting phase, so we provide the forceMount prop on many components to allow consumers to delegate the mounting and unmounting of children based on the animation state determined by those libraries.” The guidance appears in the Radix animation guide.

Separate the logical open state from the presence state

Derive a transition item from open using the animation library you selected. That item should remain present during both the entering and leaving phases. Render the Radix overlay and content while the item exists, and put forceMount on each Radix part whose mounting the library controls.

<Dialog.Root open={open} onOpenChange={setOpen}>
  <Dialog.Trigger>Open settings</Dialog.Trigger>
  <Dialog.Portal>
    {transitionItem && (
      <>
        <Dialog.Overlay forceMount className="DialogOverlay" />
        <Dialog.Content forceMount className="DialogContent">
          <Dialog.Title>Settings</Dialog.Title>
          <Dialog.Close>Close</Dialog.Close>
        </Dialog.Content>
      </>
    )}
  </Dialog.Portal>
</Dialog.Root>

transitionItem above is deliberately the animation library’s presence value, not the raw open boolean. It must stay truthy while the library is running the leave animation and become false only when the library reports completion. At that point the conditional block disappears and Radix can unmount the parts.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Mount every part whose removal is animated

If the overlay fades out but the content is removed immediately, the result will still look broken. Apply the same presence strategy to every primitive part that needs a leave phase. Conversely, do not force-mount unrelated parts unless the animation library actually manages them; unnecessary persistent nodes complicate the lifecycle.

Close flow in four events

  1. The user activates a close control, presses Escape, or otherwise changes the dialog state.
  2. onOpenChange(false) updates the logical state.
  3. The animation library keeps its transition item present and starts the leave animation; Radix parts remain mounted because of forceMount.
  4. When the animation finishes, the library removes the transition item. The conditional render ends and the overlay and content unmount.

If step four never occurs, inspect the animation library’s completion callback or presence state. If step three is skipped, check that the conditional render uses the library’s leave-aware value rather than open.

Rapid reopen and interrupted closes

A close can be followed by an immediate reopen before the leave animation completes. The presence owner should be the source of truth for that transition, rather than a separate boolean that removes the nodes prematurely. If the library reverses or interrupts the animation, keep the same mounted instance and let its documented state determine whether it finishes leaving or returns to the open phase. Avoid changing keys during this handoff, because a new key represents a different element and can defeat the intended leave lifecycle.

Rank #3
Sale
BladeHawks RGB Gaming Mouse Pad Extra Large Extended 31.5x12 Inch-Black | LED mouse pad with 14 lighting modes, covers keyboard & mouse, anti-slip rubber base, waterproof surface, USB powered
  • 【Large size】:Measuring 800 x 300 mm/ 31. 5×12 inches, which is wider and taller than others. Large mouse pad can perfectly fit your keyboard and mouse of any size, and there is also ample space for peripherals such as phones, tablets, etc.
  • 【LED backlight mouse pad】:Blade Hawks RGB mouse pad provides 7 static modes and 7 dynamic modes will give you the options you are looking for. Power-off memory function remembers the last lighting mode you selected. The super glow fiber Chroma will give you a colorful gaming setup that you want.
  • 【Anti-slip rubber base】:Made from Natural rubber, this gaming mousepad will firmly grip your desktop, allowing you to enjoy the ultimate precision in the games you are most passionate about. It also comes with a texture that enhances this ability even further.
  • 【Smooth and waterproof surface】: Micro-textured cloth surface, for extremely precise mouse control and a smooth movement. When liquid splashes on the gaming mouse pad, it forms water droplets and slides down. Will not delay your work or gameplay.
  • 【Plug and play】: This mouse and keyboard pad is powered by USB, plug and play, no driver required. One button control light modes. Press one time to change the lighting mode, press twice to change the brightness, press and hold about 3 seconds turn ON/OFF.

Motion for React with AnimatePresence

Motion’s AnimatePresence detects when one of its direct children is removed from the React tree and gives that child an exit-animation lifecycle. The documented minimal pattern is:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<AnimatePresence>
  {show && <motion.div key="dialog" exit={{ opacity: 0 }} />}
</AnimatePresence>

For a dialog, replace the motion element with the component that should animate out and keep the AnimatePresence boundary itself mounted:

<AnimatePresence>
  {open && (
    <motion.div
      key="dialog"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    >
      <DialogContent />
    </motion.div>
  )}
</AnimatePresence>

Place the boundary where removal happens

This placement rule is the part most often missed. If an ancestor removes the entire AnimatePresence at the same time as the dialog, Motion cannot observe the child leaving because the observer disappeared with it. Keep the boundary rendered and conditionally remove its direct child. The same principle applies when wrapping a Radix dialog: the Motion presence boundary must surround the part whose removal it controls, while Radix’s own forceMount is used when Radix would otherwise unmount that part first.

Give the exiting child a stable key

Use a stable key such as dialog for one dialog instance. If the key changes while closing, React treats the element as a different child, which can turn a leave into a replacement. When several dialogs can be present, give each instance a distinct stable key and place each conditional child under the presence boundary that owns it.

The same direct-child rule applies if you animate an overlay and content separately. Put each conditionally removed motion child under the boundary that is responsible for it, or wrap both in one stable motion child when they should share one exit lifecycle. Do not hide the actual removed child behind a parent that disappears first.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

React ViewTransition: a framework-level alternative

React’s current ViewTransition reference describes enter and exit animations for ViewTransitions that are added or removed by a component update performed inside a transition. Its example updates state with startTransition: React ViewTransition.

startTransition(() => {
  setOpen(false);
});

The approach is version-sensitive. Confirm that the React version and renderer used by your project support the documented API, and follow the transition constraints in that version’s reference. Do not present ViewTransition as a drop-in replacement for Radix presence or Motion’s exit lifecycle without that check. The key requirement remains the same: the update must be performed in the transition mechanism that knows an element is being removed.

This option is best considered when the application already uses the current React transition APIs. It is not a reason to remove a dialog with a plain conditional render and hope that a browser animation will preserve it. Verify the documented setup first, then confirm in the DOM that the removed view remains available for the transition.

Why a portal does not keep a dialog mounted

A portal changes where React places DOM nodes, not how React ownership works. React’s createPortal reference states that a portal’s content still acts as a child of the component that renders it: createPortal. Therefore, this does not create an exit phase:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
Vaydeer Wrist Rest for Keyboard and Mouse, Computer Ergonomic Wrist Support Pad, Soft Memory Foam Arm Cushion for Desk, Palm Hand Office Laptop Typing
  • 【Softer and More Comfortable】Vaydeer wrist rest has unique diamond pattern, which is the combination of softness and aesthetics. The materials of wrist rest are improved into higher quality memory foam and covered with silky smooth lycra. The computer wrist rest makes you as comfortable and cushiony as like rest your wrists on clouds.
  • 【Ergonomic Wrist Saver】The wrist rests for keyboard and mouse comes with a 17.32×3.15×0.83 inch keyboard wrist pad and a 5.94×3.15×0.83 inch mouse wrist support. Based on ergonomic design, the unique concave shape is the perfect fit for your wrist joints. The wrist rest pad fits most computer keyboards and laptops, improve hand and wrist posture, release your wrist and arm stress.
  • 【Non-Slip Rubber Bottom】Featuring an anti-skid silicone base on the bottom, this wrist keyboard support stays firmly in place on your desk, preventing the padding from sliding around, ensuring stable and consistent wrist support during extended computer sessions.
  • 【Better Experience & Pain Relief】Our keyboard arm rest is beneficial to alleviate the soreness caused by direct contact and friction between your arm and a hard desk surface, reducing the risk of wrist fatigue or carpal tunnel. The soft texture of memory foam can evenly distribute the pressure around your wrists and provide good support with just enough give.
  • 【Helpful in Multiple Scenarios】Whether you're working, studying, writing, typing, gaming, this keyboard and mouse rest combo is an essential accessory to add comfort and support to your hands and wrists. It’s also a great gift for men, women, family, friend, coworker, gamer, teacher, etc.
{open && createPortal(<Dialog />, document.body)}

When open becomes false, the component still conditionally removes the portal child. Put the presence boundary around the condition (or use the dialog library’s presence behavior) so the portal remains rendered until the leave animation completes.

For the same reason, moving a dialog to document.body does not transfer responsibility for focus, state, or unmounting to the browser. The React component that renders the portal still determines whether its child exists. Solve presence at that React boundary.

Activity is a separate state-preservation concern

React’s current Activity reference describes preserving hidden component state, which is different from allowing an unmount animation to finish. Activity may be relevant when a dialog should become hidden while retaining ephemeral state, but its reference does not establish it as the default solution for modal exit presence. Treat hidden-state preservation and leave-animation timing as separate design decisions. Choose the animation owner for the latter, and use Activity only when its documented behavior matches the former requirement.

Diagnose a dialog that disappears before its animation

The element vanishes immediately

  • Search for a parent expression such as {open && ...} that removes the whole dialog, portal or animation boundary.
  • Move the conditional child inside the boundary that owns presence: Radix’s state-driven primitives, AnimatePresence, or your JavaScript library’s transition item.
  • With Radix and JavaScript animation, add forceMount to every animated primitive part.

The open animation works but the close animation does not

  • Verify that a closed CSS keyframe is selected by data-state="closed"; an enter-only keyframe cannot animate the leave phase.
  • Check that the element remains mounted after open changes. A successful enter animation does not prove that the close lifecycle is wired.
  • If JavaScript owns the animation, confirm that the presence value remains true during leave instead of mirroring open exactly.

The overlay fades but the content snaps away

  • The overlay and content have separate lifecycles. Keep both mounted through the leave phase if both animate.
  • Apply the same completion rule to each part, or let one shared transition item control both.

Motion never runs exit

  • Ensure AnimatePresence is still mounted when the child is removed.
  • Make the exiting element a direct child of the boundary, not a child hidden behind an ancestor that disappears.
  • Give the child a stable key and remove that child conditionally.

Radix unmounts while a JavaScript animation is active

Use the documented delegation model: render the parts while the animation library reports presence and add forceMount to those parts. Radix’s ordinary open-state behavior is not a substitute for the library’s leave state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The animation ends but the node never disappears

Inspect the completion path in the opposite direction. A presence value that remains true after the library reports completion, a transition item that is never cleared, or an outer conditional that still renders the boundary will leave inert nodes in the tree. Confirm that the completion callback changes the value used by the actual conditional render, not merely a visual style.

Only one close path animates

Dialogs can close through a close button, Escape, an overlay interaction, or an external state update. All of those paths should reach the same onOpenChange(false) and presence lifecycle. If one path directly unmounts the component, it bypasses the animation owner. Trace every caller that can set open to false.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Testing the leave phase

Test closing as a timeline, not only as a final screenshot. Trigger each close path, inspect the DOM while the animation is running, and verify that the overlay and content still exist during the leave phase. Then verify that they are removed after the owner reports completion. Test both a normal close and a rapid close-then-reopen sequence if your animation library supports interruption.

When debugging, temporarily lengthen the example duration or slow the JavaScript animation so the intermediate DOM is observable. This does not change the implementation rule; it simply makes an incorrectly placed conditional easier to see. Also test the state where the dialog opens, closes, and opens again, because a stale transition item or changed key often appears only on the second cycle.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A practical implementation checklist

  1. Identify the exact DOM nodes that need an exit effect: overlay, content, or both.
  2. Decide whether CSS keyframes, a JavaScript animation library, Motion, or React ViewTransition owns the leave timeline.
  3. Keep that owner mounted while the conditional dialog child is removed.
  4. Use Radix’s data-state="open" and data-state="closed" selectors for the documented CSS-keyframe route.
  5. Use Radix forceMount when a JavaScript library controls mounting and unmounting.
  6. Put Motion’s AnimatePresence around the direct child that is actually removed.
  7. For ViewTransition, verify the React version and perform the state update inside the documented transition API.
  8. Keep stable keys for animated instances, especially when a close can be interrupted by a reopen.
  9. Trace every close path so none bypasses the presence owner.
  10. Test the close path, not just opening: watch the DOM while the animation runs and confirm removal occurs only after completion.

Which pattern should you use?

Choose Radix’s CSS-keyframe behavior when the dialog already uses Radix and the animation can be expressed as standard CSS keyframes. It keeps the component model small and lets Radix suspend unmounting for the recognized animation. The guide’s phrase “The simplest way is with CSS” describes this narrow, documented route—not a promise that every CSS transition is observed.

Best Value
Sale
Under Desk Cable Management Tray No Drill, Metal Mesh Cable Management Under Desk with Clamp Mount, 2 Hole Cable Tray with Wire Management and Cord Organizer for Home Office Standing Desk
  • 【No Drill Mounted】Cable management tray can be assembled in as little as 3 minutes or less-simply. Side clips easily clampe the edge of desk, pass through the holes on the sides, and secure excess cables with baskets. Desk cable management supports inward or outward installation to meet your needs in different scenarios, and provides you with great convenience when collecting and organizing wires.
  • 【Rubber Pad Protects Desk】Wire organizer under desk built-in soft rubber pads on the clamp protect your desk from scratches, so you will not damage your furniture or office.
  • 【Sturdy and Beautiful】Cord management under desk is made of high-quality carbon steel and holds about 15 lbs. The wire basket has 2 holes on each side of the tray to enable your cables to pass freely. Cable baskets are suitable for desk thickness use from 0.4" to 2.4".
  • 【Space Saving & Keep Organized】Desk cable management tray holds all your power cords, outlet strips, USB hubs and computer transformers hidden from your feet, and the data cables will not enter the vacuum cleaner to keep your desk clean and tidy. Desk wire organizer is also suitable for use in the kitchen and outdoors.
  • 【Reduce Safety Risks】Cable tray under desk keeps all plugs away from your kids, no more worry about tripping. Using 2 holes wire tray saves extra space, helps you easily cabling and wire protection. The mesh design is not easy to accumulate dust, but avoids safety accidents caused by messy wires.

Choose Radix with forceMount when a spring or tween library must determine exactly when leaving ends. The additional presence state is intentional: logical closure and physical removal are separate events. This is also the clearest option when both overlay and content need to share one JavaScript-controlled leave phase.

Choose Motion when Motion already owns the dialog animation and you can keep AnimatePresence mounted around the directly conditional child. Choose React ViewTransition only after confirming the project’s React version and the transition constraints documented for it. In every case, the invariant is unchanged: do not remove the animated node until its exit lifecycle has finished.

Frequently Asked Questions

Why doesn’t my dialog exit animation run?

The dialog is probably being removed in the same render that sets open to false. Keep the animated node mounted during a leave phase and let Radix, Motion, or the JavaScript animation library remove it after completion.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How do I keep a modal mounted while it closes?

Separate logical open state from presence state. With Radix CSS keyframes, render the parts normally and provide data-state="closed" keyframes. With JavaScript animation, render while the transition item is present and add forceMount to the animated Radix parts.

How do I animate a Radix Dialog on exit?

Use Radix’s documented CSS-keyframe approach for state-driven effects, including closed keyframes on the overlay and content. If a JavaScript library owns the timeline, delegate mounting with forceMount and remove the parts only when that library reports the leave complete.

Why does the overlay fade out but the dialog content disappear immediately?

Overlay and content are separate nodes with separate lifecycles. Keep both mounted through the leave phase and apply the same presence value, or use one shared transition item that controls both.

Can a portal keep the dialog alive during its exit animation?

No. A portal changes the DOM location but the portal content remains a React child of the component that renders it. The condition around the portal still controls removal, so place the presence boundary around that condition.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I use React Activity for a closing dialog?

Activity is documented as a way to preserve hidden component state, not as the default modal exit-presence mechanism. Choose the dialog or animation library’s leave lifecycle for exit timing, and consider Activity separately when state preservation is the actual requirement.

The Bottom Line

Set the dialog’s logical open state to false immediately, but keep its animated overlay and content mounted until the presence owner reports completion. Use Radix’s recognized CSS keyframes for the simple route, Radix forceMount when JavaScript owns removal, Motion’s directly observed child under AnimatePresence, or the documented React ViewTransition API after checking version support. A portal alone cannot provide the missing leave phase.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.