You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 08:31:11