HeadlessUI Dialog组件Transition动画不生效问题(Next.js 14.1.3)
解决HeadlessUI Dialog过渡动画不生效问题
针对你遇到的Next.js 14 + HeadlessUI Dialog无过渡动画的问题,以下是具体排查和修复步骤:
1. 修正Props名称不匹配问题
你的Modal组件定义接收的props是isOpened,但调用时传递的是modalOpened,导致Transition的show属性无法正确获取弹窗状态,动画根本无法触发。
修改AddProduct.tsx的调用代码:
<AddProductModal isOpened={modalOpened} // 改为与组件定义一致的props名称 onClose={() => setModalOpened(false)} />
2. 给Modal组件添加客户端指令
Next.js 14 App Router默认组件为服务器组件,而HeadlessUI的Transition、Dialog属于客户端交互组件,必须显式声明为客户端组件。
在Modal.tsx顶部添加:
'use client';
3. 确保样式不冲突
检查你的SCSS类(s.backdrop、s.modal)是否覆盖了Tailwind过渡类的关键属性:
- 避免给
.backdrop设置固定的opacity值,让Tailwind的enterFrom/enterTo类控制透明度变化 - 避免给
.modal设置固定的transform: scale()值,确保Tailwind的scale类能正常生效 - 可以给基础类添加过渡属性兜底,比如:
<Dialog.Overlay className={`${s.backdrop} transition-opacity`} /> <Dialog.Panel className={`${s.modal} transition-all`} />
4. 调整Transition与Dialog的结构(完整示例)
确保Transition的show与Dialog的open绑定同一个状态,保持状态同步。修改后的完整Modal.tsx示例:
'use client'; import { Fragment, ReactNode, VoidFunction } from 'react'; import { Dialog, Transition } from '@headlessui/react'; type TProps = { isOpened: boolean; onClose: VoidFunction; children?: ReactNode; }; export const Modal = ({ isOpened, onClose, children }: TProps) => { return ( <Transition show={isOpened} as={Fragment}> <Dialog as="div" className={s.modalWrapper} open={isOpened} onClose={onClose}> <Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0" enterTo="opacity-100" leave="ease-in duration-200" leaveFrom="opacity-100" leaveTo="opacity-0" > <Dialog.Overlay className={`${s.backdrop} transition-opacity`} /> </Transition.Child> <Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0 scale-95" enterTo="opacity-100 scale-100" leave="ease-in duration-200" leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95" > <Dialog.Panel className={`${s.modal} transition-all`}>{children}</Dialog.Panel> </Transition.Child> </Dialog> </Transition> ); };
完成以上步骤后,弹窗的过渡动画应该能正常触发。
内容的提问来源于stack exchange,提问作者Lvasche
相关产品推荐
相关产品推荐

