Skip to content

Refactor DrawerForm: use antd resizable api#9502

Open
zzjiaxiang wants to merge 4 commits intoant-design:masterfrom
zzjiaxiang:drawerForm
Open

Refactor DrawerForm: use antd resizable api#9502
zzjiaxiang wants to merge 4 commits intoant-design:masterfrom
zzjiaxiang:drawerForm

Conversation

@zzjiaxiang
Copy link
Contributor

@zzjiaxiang zzjiaxiang commented Feb 23, 2026

title , width(size)destroyOnHidden 属性都属于 drawerProps 里面的属性, 所以去掉专门的声明,统一集成到 drawerProps 里面.
antd6支可持调整大小了,这里移除 pro 的代码.

这几处更改都是 Breaking Change

Summary by CodeRabbit

  • 重构

    • 抽屉表单的标题与宽度相关配置已移入 drawerProps(例如 drawerProps.title / drawerProps.size),移除顶层 title/width/resize 等暴露属性。
    • 删除抽屉拖拽调整宽度的交互与相关样式、辅助接口,简化渲染与公开 API,并同步示例中相应用法。
  • 文档

    • 更新组件文档与 API 表格,反映 drawerProps 新用法并移除已删除的顶层属性。

- Set the title and size properties for DrawerForm in multiple demo files to enhance consistency.
- Removed deprecated width property and adjusted drawerProps accordingly.
- Updated documentation to reflect changes in DrawerForm properties.
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Feb 23, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @zzjiaxiang, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求重构了 DrawerForm 组件,将 titlewidth (现在是 size) 属性直接移入 drawerProps。这使得组件的 API 与 Ant Design 标准的 Drawer 组件更加一致。此外,它还移除了自定义的尺寸调整实现,转而利用 Ant Design 6 中引入的原生可调整大小功能。这简化了 DrawerForm 组件的内部逻辑并减少了冗余代码。

Highlights

  • API 统一: 将 DrawerFormtitlewidth (现为 size) 属性统一整合到 drawerProps 中,使 API 与 Ant Design 标准的 Drawer 组件保持一致。
  • 移除自定义尺寸调整: 移除了 DrawerForm 中自定义的抽屉尺寸调整逻辑,转而利用 Ant Design 6 原生支持的抽屉可调整大小功能。

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • demos/form/ModalForm/drawer-form-nested.tsx
    • titlewidth 属性移至 drawerProps
  • demos/form/ModalForm/drawer-form.tsx
    • 移除了 titleresize 属性
    • 添加了 useState 用于 size,并在 drawerProps 中配置了 resizable
  • demos/form/ModalForm/modal-form-request-destroy-debug.tsx
    • title 属性移至 drawerProps
  • demos/form/ModalForm/open-on-open-change.tsx
    • title 属性移至 drawerProps
  • site/components/modal-form.md
    • DrawerForm 的 API 文档中移除了 titlewidthresize 属性
  • src/form/layouts/DrawerForm/index.tsx
    • 移除了 clsx 导入
    • 移除了 CustomizeResizeType 类型定义
    • DrawerFormProps 中移除了 titlewidthresize 属性
    • 移除了所有与自定义尺寸调整相关的状态和逻辑
    • 通过直接展开 drawerProps 并移除显式的 titlesizedestroyOnHidden 属性,简化了 Drawer 组件的渲染
    • 移除了自定义尺寸调整手柄的 JSX
  • src/form/layouts/DrawerForm/style.ts
    • 移除了整个文件,该文件包含了自定义尺寸调整手柄的样式
Activity
  • 没有检测到任何人工活动。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

将 DrawerForm 的抽屉相关配置从顶级属性(如 titlewidthresize)迁移到 drawerProps,移除自定义拖拽缩放实现及其样式文件,示例与文档同步更新为在 drawerProps 中设置抽屉标题与尺寸相关配置。

Changes

Cohort / File(s) Summary
核心实现
src/form/layouts/DrawerForm/index.tsx
移除顶级 titlewidthresize props;删除自定义缩放类型与拖拽/尺寸状态与处理;简化渲染逻辑,改为通过 drawerProps 传递抽屉配置,并移除相关样式/钩子依赖。
样式移除
src/form/layouts/DrawerForm/style.ts
删除样式模块:DrawerFormTokengenDrawerFormStyleuseStyle 被移除。
示例:抽屉示例
demos/form/ModalForm/drawer-form.tsx
新增 useState 管理抽屉尺寸,移除原有顶级 resize/width/title 配置,改为通过 drawerProps.sizedrawerProps.onResize/drawerProps.title 传递。
示例:嵌套抽屉
demos/form/ModalForm/drawer-form-nested.tsx
将外层与内层 DrawerForm 的 title 从顶级移至 drawerProps.title;保留 forceRender 与 destroyOnHidden。
示例:销毁/请求调试
demos/form/ModalForm/modal-form-request-destroy-debug.tsx
将 DrawerForm 的 title 移入 drawerProps.title,并保持 drawerProps.destroyOnHidden 设置不变。
示例:打开状态变化
demos/form/ModalForm/open-on-open-change.tsx
将 DrawerForm 的 title 属性迁移到 drawerProps.title;open 与 onOpenChange 控制流不变。
文档
site/components/modal-form.md, site/components/modal-form.en-US.md
更新 API 表与说明:移除 DrawerForm 顶级的 titlewidthresize 条目,调整 drawerProps 的描述与引用链接(指向 Drawer API)。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 抽屉的标题搬新家,
属性悄悄进了 drawerProps,
拖拽把手轻轻放下,
示例与文档齐刷刷,
小兔子为简洁鼓掌 🥕🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确总结了主要改动:将DrawerForm的自定义调整API替换为Ant Design原生resizable API,这是本PR的核心目标。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request refactors the DrawerForm component by moving title and width properties into drawerProps for better consistency and removes the custom resize logic in favor of Ant Design's built-in resizable drawer functionality. The changes simplify the DrawerForm component's API and align it with Ant Design's latest features. The documentation and examples have been updated accordingly.

I am having trouble creating individual review comments. Click here to see my feedback.

demos/form/ModalForm/drawer-form-nested.tsx (35-37)

medium

The title and width props are being removed from the DrawerForm component directly. They should now be passed within the drawerProps object to maintain consistency with the refactored DrawerForm API.

demos/form/ModalForm/drawer-form-nested.tsx (61)

medium

The title prop is being removed from the DrawerForm component directly. It should now be passed within the drawerProps object to maintain consistency with the refactored DrawerForm API.

demos/form/ModalForm/drawer-form.tsx (28-35)

medium

The title and resize props are being removed from the DrawerForm component directly. These functionalities are now handled within drawerProps for a more unified API.

demos/form/ModalForm/modal-form-request-destroy-debug.tsx (32)

medium

The title prop is being removed from the DrawerForm component directly. It should now be passed within the drawerProps object to maintain consistency with the refactored DrawerForm API.

demos/form/ModalForm/open-on-open-change.tsx (117)

medium

The title prop is being removed from the DrawerForm component directly. It should now be passed within the drawerProps object to maintain consistency with the refactored DrawerForm API.

site/components/modal-form.md (70-72)

medium

The title, width, and resize properties are removed from the DrawerForm API documentation. This reflects the refactoring where these properties are now managed within drawerProps.

src/form/layouts/DrawerForm/index.tsx (62-72)

medium

The title, width, and resize props are removed from the DrawerFormProps interface. These properties are now expected to be passed within the drawerProps object.

src/form/layouts/DrawerForm/index.tsx (81-83)

medium

The title, width, and resize props are destructured from the component props. These are no longer directly accepted by DrawerForm and should be removed.

src/form/layouts/DrawerForm/index.tsx (92-109)

medium

The resizeInfo memoization and related logic for custom resizing are removed. This functionality is now handled by Ant Design's native resizable prop within DrawerProps.

src/form/layouts/DrawerForm/index.tsx (119-123)

medium

The resizableDrawer state and drawerWidth state, along with their initialization, are removed. These were part of the custom resize implementation which is now deprecated.

src/form/layouts/DrawerForm/index.tsx (189-191)

medium

The conditional logic for resizableDrawer and setDrawerWidth is removed. This was part of the custom resize implementation which is no longer used.

src/form/layouts/DrawerForm/index.tsx (192)

medium

The resizableDrawer dependency is removed from the useEffect hook's dependency array, as it is no longer relevant after the custom resize logic removal.

  }, [propsOpen, open]);

src/form/layouts/DrawerForm/index.tsx (212)

medium

The setResizableDrawer call is removed from the onClick handler. This was part of the custom resize implementation which is no longer used.

src/form/layouts/DrawerForm/index.tsx (216)

medium

The setResizableDrawer and resizableDrawer dependencies are removed from the useMemo hook's dependency array, as they are no longer relevant after the custom resize logic removal.

  }, [setOpen, trigger, open]);

src/form/layouts/DrawerForm/index.tsx (311-336)

medium

The cbHandleMouseMove and cbHandleMouseUp callbacks, which implemented the custom drawer resizing logic, are removed. This functionality is now handled by Ant Design's native resizable prop.

src/form/layouts/DrawerForm/index.tsx (342-346)

medium

The destroyOnHidden, title, and size props are removed from the Drawer component directly. These are now expected to be passed within the drawerProps object.

src/form/layouts/DrawerForm/index.tsx (373-389)

medium

The conditional rendering of the sidebar-dragger div and its associated onMouseDown logic are removed. This was part of the custom resize implementation which is no longer used.

src/form/layouts/DrawerForm/style.ts (1-43)

medium

The style.ts file, which contained custom styling for the resizable drawer, is completely removed. This is consistent with the refactoring to use Ant Design's native resizable drawer functionality.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

> [!CAUTION]

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/form/layouts/DrawerForm/index.tsx (3)

21-53: ⚠️ Potential issue | 🟠 Major

移除 title/width 属于 Breaking Change,需提供迁移路径

titlewidthDrawerFormProps 中删除,意味着所有在 <DrawerForm title="..." width={600}> 上直接使用这两个属性的存量代码将静默失效(TypeScript 用户会收到编译报错,JS 用户会无声无息地丢失这两个属性)。

建议先以 @deprecated 方式保留这两个 prop,内部转发给 drawerProps,并在 CHANGELOG 中说明迁移路径,待下一个 major 版本再彻底移除。

export type DrawerFormProps<
  T = Record<string, any>,
  U = Record<string, any>,
> = Omit<FormProps, 'onFinish' | 'title'> &
  CommonFormProps<T, U> & {
+   /**
+    * `@deprecated` 请使用 drawerProps.title 代替
+    */
+   title?: DrawerProps['title'];
+   /**
+    * `@deprecated` 请使用 drawerProps.width 代替
+    */
+   width?: DrawerProps['width'];
    ...
    drawerProps?: Omit<DrawerProps, 'open'>;
  };

对应在组件函数内部:

function DrawerForm<T = Record<string, any>, U = Record<string, any>>({
  children,
  trigger,
  drawerProps,
+ title,
+ width,
  ...
}: DrawerFormProps<T, U>) {
  ...
  // 将 deprecated 的 prop 合并到 drawerProps
+ const mergedDrawerProps = { title, width, ...drawerProps };

根据编码规范:"Maintain backward compatibility and avoid breaking changes"。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 21 - 53, DrawerFormProps
currently removed title and width which is a breaking change; restore them as
optional (mark with `@deprecated`) in the DrawerFormProps type and update the
DrawerForm component to forward any deprecated title/width into drawerProps
(e.g., if title !== undefined set drawerProps.title = title; if width !==
undefined set drawerProps.width = width) while keeping onFinish/submitTimeout
behavior unchanged; also ensure the component emits a console.warn or logger
deprecation message when deprecated props are used and document the migration in
the CHANGELOG so these props can be removed in the next major version.

256-270: ⚠️ Potential issue | 🟡 Minor

afterOpenChangequeueMicrotask 双重触发 onOpenChange

setOpen 通过 queueMicrotask 已经异步通知了 onOpenChangeCallback(Line 98–100),而 afterOpenChange 回调又在抽屉动画完成后再次调用 onOpenChange?.(open)(Line 266),导致每次开/关操作 onOpenChange 均被触发两次。

对于受控模式(通过 propsOpen 控制),还会叠加 useEffect(Line 136)中的第三次调用。

建议从 afterOpenChange 中移除 onOpenChange?.(open) 调用,仅保留对用户自定义 drawerProps.afterOpenChange 的透传:

afterOpenChange={(open) => {
  if (!open && drawerProps?.destroyOnHidden) {
    resetFields();
  }
  drawerProps?.afterOpenChange?.(open);
- onOpenChange?.(open);
}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 256 - 270, The
afterOpenChange handler in Drawer currently calls onOpenChange?.(open) which
duplicates notifications already dispatched asynchronously by setOpen (via
queueMicrotask in the onOpenChangeCallback) and can cause a third call from the
useEffect in controlled mode; remove the onOpenChange?.(open) invocation from
the afterOpenChange block and only forward to
drawerProps?.afterOpenChange?.(open) so user-provided drawerProps callback still
runs but the duplicate onOpenChange call is eliminated.

134-138: ⚠️ Potential issue | 🟡 Minor

onOpenChange 未加入 useEffect 依赖数组 — 存在陈旧闭包风险

onOpenChange 在 effect 内部直接被调用,但未被列入依赖数组。若调用方传入的是非稳定引用的函数,该 effect 将始终持有其旧版本。

-}, [propsOpen, open]);
+}, [propsOpen, open, onOpenChange]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 134 - 138, The effect in
DrawerForm (useEffect that checks if open && propsOpen and calls
onOpenChange?.(true)) uses onOpenChange without listing it in the dependency
array, risking a stale closure; update the effect to include onOpenChange in the
dependency array (i.e., [propsOpen, open, onOpenChange]) or alternatively
stabilize the callback passed into the component (e.g., wrap the prop with
useCallback/useRef) so that the onOpenChange used inside useEffect is always
current.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/form/layouts/DrawerForm/index.tsx`:
- Around line 21-53: DrawerFormProps currently removed title and width which is
a breaking change; restore them as optional (mark with `@deprecated`) in the
DrawerFormProps type and update the DrawerForm component to forward any
deprecated title/width into drawerProps (e.g., if title !== undefined set
drawerProps.title = title; if width !== undefined set drawerProps.width = width)
while keeping onFinish/submitTimeout behavior unchanged; also ensure the
component emits a console.warn or logger deprecation message when deprecated
props are used and document the migration in the CHANGELOG so these props can be
removed in the next major version.
- Around line 256-270: The afterOpenChange handler in Drawer currently calls
onOpenChange?.(open) which duplicates notifications already dispatched
asynchronously by setOpen (via queueMicrotask in the onOpenChangeCallback) and
can cause a third call from the useEffect in controlled mode; remove the
onOpenChange?.(open) invocation from the afterOpenChange block and only forward
to drawerProps?.afterOpenChange?.(open) so user-provided drawerProps callback
still runs but the duplicate onOpenChange call is eliminated.
- Around line 134-138: The effect in DrawerForm (useEffect that checks if open
&& propsOpen and calls onOpenChange?.(true)) uses onOpenChange without listing
it in the dependency array, risking a stale closure; update the effect to
include onOpenChange in the dependency array (i.e., [propsOpen, open,
onOpenChange]) or alternatively stabilize the callback passed into the component
(e.g., wrap the prop with useCallback/useRef) so that the onOpenChange used
inside useEffect is always current.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a07592d and f73f96c.

📒 Files selected for processing (7)
  • demos/form/ModalForm/drawer-form-nested.tsx
  • demos/form/ModalForm/drawer-form.tsx
  • demos/form/ModalForm/modal-form-request-destroy-debug.tsx
  • demos/form/ModalForm/open-on-open-change.tsx
  • site/components/modal-form.md
  • src/form/layouts/DrawerForm/index.tsx
  • src/form/layouts/DrawerForm/style.ts
💤 Files with no reviewable changes (2)
  • site/components/modal-form.md
  • src/form/layouts/DrawerForm/style.ts

@zzjiaxiang zzjiaxiang changed the title Refactor DrawerForm: Refactor DrawerForm: use antd resizable api Feb 24, 2026
…rect drawerProps links

- Removed the 'resize' and 'width' properties from the documentation as they are no longer supported.
- Updated the 'drawerProps' link to point to the correct antd documentation.
- Cleaned up the 'open' property description for clarity.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/form/layouts/DrawerForm/index.tsx (2)

256-267: ⚠️ Potential issue | 🟡 Minor

避免 onOpenChange 被调用两次。

setOpen 已通过 onOpenChangeCallback 触发回调,这里又在 afterOpenChange 里调用一次,会导致内部触发的开关事件回调重复,可能引发重复副作用。

🧩 建议修改
         afterOpenChange={(open) => {
           if (!open && drawerProps?.destroyOnHidden) {
             resetFields();
           }
           drawerProps?.afterOpenChange?.(open);
-          onOpenChange?.(open);
         }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 256 - 267, The
afterOpenChange handler on the Drawer is calling onOpenChange again which
duplicates the callback already invoked via setOpen/onOpenChangeCallback; update
the Drawer afterOpenChange implementation (the anonymous function passed to the
Drawer component) to only run local logic (e.g., resetFields and
drawerProps?.afterOpenChange?.(open)) and remove the direct call to
onOpenChange?.(open) (or add a guard to skip calling onOpenChange when the
change originated from setOpen/onOpenChangeCallback) so the onOpenChange
callback is not invoked twice.

21-53: ⚠️ Potential issue | 🟠 Major

为避免破坏性变更,建议保留顶层兼容字段并做弃用映射。

当前移除 title / width(size) / destroyOnHidden 的顶层字段会让现有调用方在升级时直接编译/运行失败。建议临时保留这些字段(标注 @deprecated),并在运行时合并到 drawerProps,同时 noteOnce 提示迁移,以便平滑升级。

🛠️ 建议实现(示例)
 export type DrawerFormProps<
   T = Record<string, any>,
   U = Record<string, any>,
 > = Omit<FormProps, 'onFinish' | 'title'> &
   CommonFormProps<T, U> & {
+    /** `@deprecated` 请使用 drawerProps.title */
+    title?: DrawerProps['title'];
+    /** `@deprecated` 请使用 drawerProps.size */
+    size?: DrawerProps['size'];
+    /** `@deprecated` 请使用 drawerProps.width */
+    width?: DrawerProps['width'];
+    /** `@deprecated` 请使用 drawerProps.destroyOnHidden */
+    destroyOnHidden?: DrawerProps['destroyOnHidden'];
     /** `@name` antd的Drawer组件[props](https://ant-design.antgroup.com/components/drawer#api) */
     drawerProps?: Omit<DrawerProps, 'open'>;
   };
 function DrawerForm<T = Record<string, any>, U = Record<string, any>>({
   children,
   trigger,
   drawerProps,
+  title,
+  size,
+  width,
+  destroyOnHidden,
   onFinish,
   submitTimeout,
   onOpenChange,
   open: propsOpen,
   ...rest
 }: DrawerFormProps<T, U>) {
+  noteOnce(
+    !title && !size && !width && !destroyOnHidden,
+    'DrawerForm 的 title/size/width/destroyOnHidden 已废弃,请迁移到 drawerProps。',
+  );
+
+  const mergedDrawerProps = useMemo(
+    () => ({
+      ...drawerProps,
+      title: drawerProps?.title ?? title,
+      size: drawerProps?.size ?? size,
+      width: drawerProps?.width ?? width,
+      destroyOnHidden: drawerProps?.destroyOnHidden ?? destroyOnHidden,
+    }),
+    [drawerProps, title, size, width, destroyOnHidden],
+  );
       <Drawer
-        {...drawerProps}
+        {...mergedDrawerProps}
         open={open}

As per coding guidelines, Maintain backward compatibility and avoid breaking changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 21 - 53, The PR removed
top-level props (title, width/size, destroyOnHidden) from DrawerFormProps which
will break callers; restore these top-level fields as `@deprecated` in
DrawerFormProps and at runtime merge their values into drawerProps when present
(e.g., detect deprecatedTitle/deprecatedWidth/deprecatedDestroyOnHidden and copy
them into drawerProps before rendering), emit a one-time migration warning
(noteOnce) advising users to move to drawerProps, and keep existing props like
onFinish, submitTimeout, trigger, open, onOpenChange untouched; update type
definitions and the component's props handling to prefer drawerProps values but
fall back to the deprecated top-level values when provided.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/form/layouts/DrawerForm/index.tsx`:
- Around line 256-267: The afterOpenChange handler on the Drawer is calling
onOpenChange again which duplicates the callback already invoked via
setOpen/onOpenChangeCallback; update the Drawer afterOpenChange implementation
(the anonymous function passed to the Drawer component) to only run local logic
(e.g., resetFields and drawerProps?.afterOpenChange?.(open)) and remove the
direct call to onOpenChange?.(open) (or add a guard to skip calling onOpenChange
when the change originated from setOpen/onOpenChangeCallback) so the
onOpenChange callback is not invoked twice.
- Around line 21-53: The PR removed top-level props (title, width/size,
destroyOnHidden) from DrawerFormProps which will break callers; restore these
top-level fields as `@deprecated` in DrawerFormProps and at runtime merge their
values into drawerProps when present (e.g., detect
deprecatedTitle/deprecatedWidth/deprecatedDestroyOnHidden and copy them into
drawerProps before rendering), emit a one-time migration warning (noteOnce)
advising users to move to drawerProps, and keep existing props like onFinish,
submitTimeout, trigger, open, onOpenChange untouched; update type definitions
and the component's props handling to prefer drawerProps values but fall back to
the deprecated top-level values when provided.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f73f96c and f69aeed.

📒 Files selected for processing (3)
  • site/components/modal-form.en-US.md
  • site/components/modal-form.md
  • src/form/layouts/DrawerForm/index.tsx
✅ Files skipped from review due to trivial changes (1)
  • site/components/modal-form.en-US.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • site/components/modal-form.md

… and Chinese versions

- Fixed the link for 'drawerProps' in both English and Chinese documentation to point to the correct antd documentation.
- Ensured consistency in property descriptions across language versions.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/form/layouts/DrawerForm/index.tsx (2)

134-138: ⚠️ Potential issue | 🟡 Minor

useEffect 缺少 onOpenChange 依赖 / 应使用稳定 ref 包装器

第 136 行在 effect 内部直接调用了 onOpenChange?.(true),但 onOpenChange 未出现在依赖数组中,存在过期闭包风险。与其他位置的用法保持一致,应改为使用已有的稳定 ref 包装器 onOpenChangeCallback

🐛 建议修复
  useEffect(() => {
    if (open && propsOpen) {
-     onOpenChange?.(true);
+     onOpenChangeCallback(true);
    }
  }, [propsOpen, open, onOpenChangeCallback]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 134 - 138, The effect
currently calls onOpenChange directly (useEffect(() => { if (open && propsOpen)
{ onOpenChange?.(true); } }, [propsOpen, open])) causing a missing-deps
stale-closure risk; replace the direct call with the stable ref wrapper
onOpenChangeCallback (e.g. call onOpenChangeCallback.current or the wrapper
function) inside the effect so you don't need to add onOpenChange to the deps,
keeping the dependency array as [propsOpen, open] and using onOpenChangeCallback
to invoke the handler safely.

261-267: ⚠️ Potential issue | 🟠 Major

onOpenChange 被重复调用(每次开/关触发两次)

setOpen 内部已通过 queueMicrotask(() => onOpenChangeCallback(next)) 调用了 onOpenChange(line 99)。而 afterOpenChange 回调(动画结束后触发)又再次直接调用了 onOpenChange?.(open)(line 266)。这会导致每次打开或关闭抽屉时,消费者的 onOpenChange 回调被触发两次。

如果 afterOpenChange 中调用 onOpenChange 的目的是在动画结束后再次通知(行为有别于 setOpen 中的即时通知),应该通过 drawerProps?.afterOpenChange 向消费者暴露动画结束事件,而非复用 onOpenChange。如果目的是保持与 antd 原生 afterOpenChange 一致的语义,则应移除此处对 onOpenChange 的直接调用。

🐛 建议修复
  afterOpenChange={(open) => {
    if (!open && drawerProps?.destroyOnHidden) {
      resetFields();
    }
    drawerProps?.afterOpenChange?.(open);
-   onOpenChange?.(open);
  }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 261 - 267, The
afterOpenChange handler currently calls onOpenChange directly causing duplicate
notifications because setOpen already queues onOpenChange; remove the direct
call to onOpenChange in the afterOpenChange block and only invoke
drawerProps?.afterOpenChange?.(open) (and keep resetFields logic) so consumers
receive the animation-end event via drawerProps.afterOpenChange instead of a
second onOpenChange invocation; locate the logic around afterOpenChange in
DrawerForm (the afterOpenChange arrow function) and delete the
onOpenChange?.(open) call.
🧹 Nitpick comments (2)
src/form/layouts/DrawerForm/index.tsx (2)

278-283: Footer <div> 使用了内联样式

根据编码规范,应使用 Tailwind 类替代内联 style 属性。

♻️ 建议重构
          <div
            ref={footerDomRef}
-           style={{
-             display: 'flex',
-             justifyContent: 'flex-end',
-           }}
+           className="flex justify-end"
          />

As per coding guidelines: "Always use Tailwind classes for styling HTML elements; avoid using CSS or tags."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 278 - 283, The footer div
in DrawerForm (look for the <div> with inline style={{ display: 'flex',
justifyContent: 'flex-end' }} near the footer/render section of
DrawerForm/index.tsx) uses inline styles; replace these with Tailwind utility
classes (e.g., className="flex justify-end" or other appropriate Tailwind
spacing/alignment utilities) on that element and remove the style prop so
styling follows the project's Tailwind convention.

156-161: triggerDom 中的 toggle 建议使用函数式更新

setOpen(!open)useMemo 的闭包中捕获了 open,这使得 open 必须作为依赖项(line 161)。每次 open 状态变化都会重新创建 triggerDom。使用函数式更新可以去掉该依赖,并避免快速连续点击场景下的过期值问题。

♻️ 建议重构
      onClick: async (e: any) => {
-       setOpen(!open);
+       setOpen((prev) => !prev);
        trigger.props?.onClick?.(e);
      },
-   }, [setOpen, trigger, open]);
+   }, [setOpen, trigger]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 156 - 161, The toggle in
triggerDom uses setOpen(!open) inside the useMemo closure which captures stale
open and forces open to be a dependency; change this to the functional updater
form setOpen(prev => !prev) inside the onClick handler so you can remove open
from the useMemo dependency and avoid race/stale-state on rapid clicks; keep
calling trigger.props?.onClick?.(e) after updating state and ensure you update
the dependency array to [setOpen, trigger] (or as appropriate) for the memoized
triggerDom.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/form/layouts/DrawerForm/index.tsx`:
- Around line 134-138: The effect currently calls onOpenChange directly
(useEffect(() => { if (open && propsOpen) { onOpenChange?.(true); } },
[propsOpen, open])) causing a missing-deps stale-closure risk; replace the
direct call with the stable ref wrapper onOpenChangeCallback (e.g. call
onOpenChangeCallback.current or the wrapper function) inside the effect so you
don't need to add onOpenChange to the deps, keeping the dependency array as
[propsOpen, open] and using onOpenChangeCallback to invoke the handler safely.
- Around line 261-267: The afterOpenChange handler currently calls onOpenChange
directly causing duplicate notifications because setOpen already queues
onOpenChange; remove the direct call to onOpenChange in the afterOpenChange
block and only invoke drawerProps?.afterOpenChange?.(open) (and keep resetFields
logic) so consumers receive the animation-end event via
drawerProps.afterOpenChange instead of a second onOpenChange invocation; locate
the logic around afterOpenChange in DrawerForm (the afterOpenChange arrow
function) and delete the onOpenChange?.(open) call.

---

Nitpick comments:
In `@src/form/layouts/DrawerForm/index.tsx`:
- Around line 278-283: The footer div in DrawerForm (look for the <div> with
inline style={{ display: 'flex', justifyContent: 'flex-end' }} near the
footer/render section of DrawerForm/index.tsx) uses inline styles; replace these
with Tailwind utility classes (e.g., className="flex justify-end" or other
appropriate Tailwind spacing/alignment utilities) on that element and remove the
style prop so styling follows the project's Tailwind convention.
- Around line 156-161: The toggle in triggerDom uses setOpen(!open) inside the
useMemo closure which captures stale open and forces open to be a dependency;
change this to the functional updater form setOpen(prev => !prev) inside the
onClick handler so you can remove open from the useMemo dependency and avoid
race/stale-state on rapid clicks; keep calling trigger.props?.onClick?.(e) after
updating state and ensure you update the dependency array to [setOpen, trigger]
(or as appropriate) for the memoized triggerDom.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f69aeed and 37b2d40.

📒 Files selected for processing (3)
  • site/components/modal-form.en-US.md
  • site/components/modal-form.md
  • src/form/layouts/DrawerForm/index.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • site/components/modal-form.md
  • site/components/modal-form.en-US.md

…ial errors

- Updated the DrawerForm component to safely spread drawerProps, handling cases where it may be undefined.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/form/layouts/DrawerForm/index.tsx (2)

134-138: ⚠️ Potential issue | 🟠 Major

useEffect 中直接调用 onOpenChange 但未将其列入依赖数组,存在闭包陈旧问题

onOpenChange 在 effect 内部被直接调用(第 136 行),但依赖数组仅有 [propsOpen, open],违反了 react-hooks/exhaustive-deps 规则。若 onOpenChange 在父组件中是内联函数,effect 将始终持有其旧引用。

文件内已有通过 useRefFunction 包装的稳定引用 onOpenChangeCallback,应直接使用。

🐛 建议修复
  useEffect(() => {
    if (open && propsOpen) {
-     onOpenChange?.(true);
+     onOpenChangeCallback(true);
    }
  }, [propsOpen, open]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 134 - 138, The effect
currently calls onOpenChange directly but only lists [propsOpen, open] in its
dependency array, causing a stale-closure bug; change the effect to call the
stable wrapper onOpenChangeCallback (the useRefFunction-wrapped stable
reference) instead of onOpenChange, and keep the dependency array as [propsOpen,
open] so the callback used inside useEffect is always the stable
onOpenChangeCallback reference; update the useEffect that checks if (open &&
propsOpen) to invoke onOpenChangeCallback?.(true).

134-138: ⚠️ Potential issue | 🟡 Minor

通过受控 propsOpen 打开抽屉时,onOpenChange(true) 会被重复触发两次

当外部通过 propsOpen 将抽屉设为打开时:

  1. 第 134–138 行的 useEffectopen && propsOpen 均为 true)同步调用一次 onOpenChange(true)
  2. 抽屉动画结束后,第 266 行的 afterOpenChange 再次调用 onOpenChange?.(open)

消费方会连续收到两次内容相同的 true 通知。可考虑移除 useEffect 中的 onOpenChange 调用,统一由 afterOpenChange 负责通知状态变更(afterOpenChange 对打开和关闭均会触发,语义更完整)。

💡 建议修复
  useEffect(() => {
-   if (open && propsOpen) {
-     onOpenChange?.(true);
-   }
- }, [propsOpen, open]);
+   // 已由 afterOpenChange 统一处理 onOpenChange 回调,此处无需重复调用
+ }, []);

若此 useEffect 有其他意图(如 SSR 场景下的特殊处理),请在代码中添加注释说明。

Also applies to: 261-267

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/DrawerForm/index.tsx` around lines 134 - 138, 当前在 DrawerForm
的 useEffect 中(监听 propsOpen 和 open)会在受控 propsOpen 打开时调用 onOpenChange(true),但
afterOpenChange(第 266 行)在动画结束后也会再次调用 onOpenChange,导致重复通知。请移除 useEffect 中对
onOpenChange 的调用(在 useEffect 里引用的标识为 useEffect, propsOpen, open,
onOpenChange),统一由 afterOpenChange 来一次性通知打开/关闭;如果该 useEffect 有 SSR
或其它特殊意图,请在代码中保留并添加明确注释说明其必要性。
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/form/layouts/DrawerForm/index.tsx`:
- Around line 134-138: The effect currently calls onOpenChange directly but only
lists [propsOpen, open] in its dependency array, causing a stale-closure bug;
change the effect to call the stable wrapper onOpenChangeCallback (the
useRefFunction-wrapped stable reference) instead of onOpenChange, and keep the
dependency array as [propsOpen, open] so the callback used inside useEffect is
always the stable onOpenChangeCallback reference; update the useEffect that
checks if (open && propsOpen) to invoke onOpenChangeCallback?.(true).
- Around line 134-138: 当前在 DrawerForm 的 useEffect 中(监听 propsOpen 和 open)会在受控
propsOpen 打开时调用 onOpenChange(true),但 afterOpenChange(第 266 行)在动画结束后也会再次调用
onOpenChange,导致重复通知。请移除 useEffect 中对 onOpenChange 的调用(在 useEffect 里引用的标识为
useEffect, propsOpen, open, onOpenChange),统一由 afterOpenChange 来一次性通知打开/关闭;如果该
useEffect 有 SSR 或其它特殊意图,请在代码中保留并添加明确注释说明其必要性。

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37b2d40 and 2f30e66.

📒 Files selected for processing (1)
  • src/form/layouts/DrawerForm/index.tsx

@leshalv
Copy link
Collaborator

leshalv commented Feb 24, 2026

调整大小可以用ant6的,但是属性移除了旧系统没办法平滑升级

@zzjiaxiang
Copy link
Contributor Author

调整大小可以用ant6的,但是属性移除了旧系统没办法平滑升级

项目里面 peerDependencies 和官网已经指定了需要 antd > 6. 同时 pro2 -> pro3 已经有许多破坏性变更了, 我觉得咱们直接从 antd6 开始 把 Breaking Change 写到 Changelog 里面,不需要保留兼容性代码.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants