Skip to content

feat(drawer): add destroyOnClose to drawer#4153

Merged
zzcr merged 10 commits into
opentiny:devfrom
Yujing613:drawer_destroyOnClose
Jun 23, 2026
Merged

feat(drawer): add destroyOnClose to drawer#4153
zzcr merged 10 commits into
opentiny:devfrom
Yujing613:drawer_destroyOnClose

Conversation

@Yujing613

@Yujing613 Yujing613 commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Drawer 组件关闭时默认仅隐藏内容,不会销毁内部 DOM 元素。

Issue Number: N/A

What is the new behavior?

新增 destroyOnClose 属性,支持在抽屉关闭时销毁内部元素,而非隐藏。

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Added destroy-on-close prop to the drawer component, allowing drawer contents to be destroyed on close instead of hidden in the DOM (default: false).
  • Documentation

    • Added API documentation and interactive demos showing how to use the new destroy-on-close behavior.

Review Change Stack

@github-actions github-actions Bot added the enhancement New feature or request (功能增强) label Mar 27, 2026
@coderabbitai

coderabbitai Bot commented Mar 27, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 536b7826-057d-4cba-b547-76cf0c1160d6

📥 Commits

Reviewing files that changed from the base of the PR and between da3b9db and a97b96d.

📒 Files selected for processing (3)
  • examples/sites/demos/apis/drawer.js
  • examples/sites/demos/pc/app/drawer/webdoc/drawer.js
  • packages/renderless/src/drawer/index.ts

Walkthrough

This PR adds a destroy-on-close feature to the drawer component. When enabled, drawer DOM elements are removed from the tree on close rather than remaining mounted and hidden. Changes include prop definition, renderless layer updates, API documentation, demo examples in both API styles, and E2E tests validating the behavior.

Changes

Destroy-on-Close Feature

Layer / File(s) Summary
Renderless and API Documentation Updates
packages/renderless/src/drawer/index.ts, examples/sites/demos/apis/drawer.js
watchVisible parameter signature expands to include state and nextTick. New destroy-on-close prop documented as a stable boolean (default false) with localized descriptions and demo reference.
Demo Configuration and Examples
examples/sites/demos/pc/app/drawer/webdoc/drawer.js, examples/sites/demos/pc/app/drawer/destroy-on-close.vue, examples/sites/demos/pc/app/drawer/destroy-on-close-composition-api.vue, examples/sites/demos/pc/app/drawer/destroy-on-close.spec.ts
Demo registered with localized names and descriptions; Options API and Composition API examples both provide radio toggles to switch destruction behavior and a button to open the drawer; Playwright test validates both states: without destroy-on-close, the drawer element hides; with destroy-on-close, the drawer is removed from DOM.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • opentiny/tiny-vue#4195: Also modifies the watchVisible implementation in packages/renderless/src/drawer/index.ts that this PR updates; overlaps at the visibility watcher code path.

🐰 A drawer that disappears,

When closed, not just hidden in care,

Toggles two ways to play,

Examples show the day,

Tests confirm: destroy or layer! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a destroyOnClose prop to the drawer component, which is the primary objective across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

examples/sites/demos/apis/drawer.js

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

examples/sites/demos/pc/app/drawer/webdoc/drawer.js

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

packages/renderless/src/drawer/index.ts

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
packages/vue/src/drawer/src/pc.vue (1)

17-42: ⚠️ Potential issue | 🟡 Minor

The state.key++ mechanism in renderless layer is dead code.

The v-if="destroyOnClose ? state.visible : true" approach correctly handles DOM destruction. However, the renderless layer (packages/renderless/src/drawer/index.ts lines 64-67) increments state.key++ when destroyOnClose is enabled and the drawer closes, but this template never binds :key="state.key" to any element.

This means the state.key++ code path has no effect and is dead code. The feature still works because the v-if directive handles the destruction, but the renderless logic should be cleaned up to avoid confusion.

💡 Recommended: Remove dead code from renderless layer

Either:

  1. Remove state.key++ logic from packages/renderless/src/drawer/index.ts since v-if handles destruction, OR
  2. Add :key="state.key" to the drawer main div if key-based re-rendering is intended for some purpose

Option 1 (remove dead code from packages/renderless/src/drawer/index.ts):

     } else {
-      if (props.destroyOnClose) {
-        nextTick(() => state.key++)
-      }
     }

And remove state and nextTick from watchVisible parameters if no longer needed.

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

In `@packages/vue/src/drawer/src/pc.vue` around lines 17 - 42, The renderless
layer increments state.key (state.key++) in
packages/renderless/src/drawer/index.ts but the template in pc.vue never uses
:key="state.key", making that branch dead; either remove the state.key++ and
related unused watchVisible parameters (state and nextTick) from the renderless
watch logic, or wire the key into the DOM by adding :key="state.key" to the main
drawer element (the div with ref="drawerBox" / class 'tiny-drawer__main')—choose
one approach and update only the corresponding symbols (remove state.key++ and
unused watchVisible params in drawer/index.ts OR add :key="state.key" to the
drawer main div in pc.vue) so the code is consistent and dead code is
eliminated.
🧹 Nitpick comments (2)
packages/renderless/src/drawer/vue.ts (1)

34-34: Implementation is correct, but supports unused functionality.

The nextTick addition and updated watchVisible invocation are correctly implemented. However, as noted in pc.vue, the state.key++ mechanism these changes support is not utilized by the template (no :key binding exists). Consider cleaning up if the key-based re-rendering is not intended.

Also applies to: 63-63

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

In `@packages/renderless/src/drawer/vue.ts` at line 34, The change added support
for key-based re-rendering via state.key++ and updated watchVisible/nextTick
handling, but the template (e.g., in pc.vue) has no :key binding so that
mechanism is unused; either remove the state.key and nextTick-related updates
(references: state.key++, nextTick, watchVisible) or add a :key binding in the
consuming template (pc.vue) to actually use state.key for re-rendering—pick one:
delete the unused state.key++ and related nextTick logic from the drawer
renderless implementation, or wire :key="state.key" into the pc.vue template so
the key increment triggers a remount.
examples/sites/demos/pc/app/drawer/destroy-on-close-composition-api.vue (1)

1-20: LGTM! Clean and functional demo structure.

The template correctly demonstrates the destroy-on-close feature with radio controls and proper drawer integration.

♻️ Optional: Simplify visibility binding

You could simplify lines 13-14 by using v-model:visible:

     <tiny-drawer
       title="标题"
-      :visible="boxVisibility"
-      `@update`:visible="boxVisibility = $event"
+      v-model:visible="boxVisibility"
       :destroy-on-close="value"
     >

However, the explicit event handler pattern is also valid and may be clearer for demo purposes.

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

In `@examples/sites/demos/pc/app/drawer/destroy-on-close-composition-api.vue`
around lines 1 - 20, Simplify the visibility binding by replacing the explicit
:visible="boxVisibility" and `@update`:visible="boxVisibility = $event" pattern on
the tiny-drawer with the shorthand v-model:visible="boxVisibility" so the
drawer's visibility is two-way bound via boxVisibility; locate the tiny-drawer
usage in the template where boxVisibility is referenced and apply the
v-model:visible change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/sites/demos/pc/app/drawer/destroy-on-close.spec.ts`:
- Around line 9-15: The test currently opens the drawer but never closes it
before asserting; update the flow in the spec that uses demo.locator(...
'关闭时不销毁') / demo.getByRole('button', { name: '点击打开抽屉' }) and the referenced
drawer locator: after clicking the open button, first assert the drawer is
visible (toBeVisible or toHaveCount > 0), then close the drawer (e.g., use
demo.getByRole to click the drawer close button,
demo.locator('.ant-drawer-mask').click(), or send Escape) and only after that
assert the expected outcome — for the non-destroy case assert the drawer is
hidden, and for the destroy-on-close case assert drawer count is 0.

In `@examples/sites/demos/pc/app/drawer/webdoc/drawer.js`:
- Around line 135-148: The demo entry with demoId 'destroy-on-close' has two doc
issues: fill in name['en-US'] with a proper English label (e.g., "Destroy on
Close") and update the Chinese description desc['zh-CN'] to reference the Drawer
component instead of "Dialog-box" (replace "Dialog-box" with "drawer"). Edit the
object fields name['en-US'] and desc['zh-CN'] accordingly to keep translations
consistent.

In `@packages/renderless/src/drawer/index.ts`:
- Around line 64-67: Remove the unused and undefined state.key++ update: inside
the else branch that checks props.destroyOnClose and calls nextTick, delete the
nextTick(() => state.key++) call (and the associated increment logic) because
IDrawerState has no key property and the template already handles DOM
destruction via v-if="destroyOnClose ? state.visible : true"; keep the
surrounding conditional logic but eliminate references to state.key, nextTick
and the increment.

---

Outside diff comments:
In `@packages/vue/src/drawer/src/pc.vue`:
- Around line 17-42: The renderless layer increments state.key (state.key++) in
packages/renderless/src/drawer/index.ts but the template in pc.vue never uses
:key="state.key", making that branch dead; either remove the state.key++ and
related unused watchVisible parameters (state and nextTick) from the renderless
watch logic, or wire the key into the DOM by adding :key="state.key" to the main
drawer element (the div with ref="drawerBox" / class 'tiny-drawer__main')—choose
one approach and update only the corresponding symbols (remove state.key++ and
unused watchVisible params in drawer/index.ts OR add :key="state.key" to the
drawer main div in pc.vue) so the code is consistent and dead code is
eliminated.

---

Nitpick comments:
In `@examples/sites/demos/pc/app/drawer/destroy-on-close-composition-api.vue`:
- Around line 1-20: Simplify the visibility binding by replacing the explicit
:visible="boxVisibility" and `@update`:visible="boxVisibility = $event" pattern on
the tiny-drawer with the shorthand v-model:visible="boxVisibility" so the
drawer's visibility is two-way bound via boxVisibility; locate the tiny-drawer
usage in the template where boxVisibility is referenced and apply the
v-model:visible change.

In `@packages/renderless/src/drawer/vue.ts`:
- Line 34: The change added support for key-based re-rendering via state.key++
and updated watchVisible/nextTick handling, but the template (e.g., in pc.vue)
has no :key binding so that mechanism is unused; either remove the state.key and
nextTick-related updates (references: state.key++, nextTick, watchVisible) or
add a :key binding in the consuming template (pc.vue) to actually use state.key
for re-rendering—pick one: delete the unused state.key++ and related nextTick
logic from the drawer renderless implementation, or wire :key="state.key" into
the pc.vue template so the key increment triggers a remount.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7dd37db6-245b-4407-be7d-ffd4bd69d812

📥 Commits

Reviewing files that changed from the base of the PR and between d782f55 and e4226d9.

📒 Files selected for processing (9)
  • examples/sites/demos/apis/drawer.js
  • examples/sites/demos/pc/app/drawer/destroy-on-close-composition-api.vue
  • examples/sites/demos/pc/app/drawer/destroy-on-close.spec.ts
  • examples/sites/demos/pc/app/drawer/destroy-on-close.vue
  • examples/sites/demos/pc/app/drawer/webdoc/drawer.js
  • packages/renderless/src/drawer/index.ts
  • packages/renderless/src/drawer/vue.ts
  • packages/vue/src/drawer/src/index.ts
  • packages/vue/src/drawer/src/pc.vue

Comment thread examples/sites/demos/pc/app/drawer/destroy-on-close.spec.ts
Comment thread examples/sites/demos/pc/app/drawer/webdoc/drawer.js
Comment thread packages/renderless/src/drawer/index.ts Outdated
zzcr
zzcr previously approved these changes Mar 31, 2026
@zzcr

zzcr commented Mar 31, 2026

Copy link
Copy Markdown
Member

@Yujing613 E2E测试用例报错了,有空看下哈

@Issues-translate-bot

Copy link
Copy Markdown

Bot detected the issue body's language is not English, translate it automatically.


@Yujing613 The E2E test case reported an error, take a look when you have time.

@Yujing613
Yujing613 requested a review from zzcr April 14, 2026 07:06
Comment thread examples/sites/demos/apis/drawer.js Outdated
Comment thread packages/renderless/src/drawer/index.ts Outdated
@Yujing613
Yujing613 requested a review from zzcr June 11, 2026 06:14
@zzcr
zzcr merged commit 04e52d2 into opentiny:dev Jun 23, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request (功能增强)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants