Skip to content

Conversation

@GBcui
Copy link

@GBcui GBcui commented Sep 10, 2025

MentionSender, Sender组件
1、新增 openHeader 属性,方便控制自定义头部,默认展开关闭。
2、向下兼容openHeader和closeHeader方法。
3、中英文档 添加 openHeader 属性 并调整组件示例代码
Refs: #319

Summary by CodeRabbit

  • New Features
    • Sender and MentionSender now support openHeader with v-model:openHeader, emitting update:openHeader for two-way header visibility control.
  • Documentation
    • EN/zh docs and demos updated to showcase v-model usage; prop tables added; imperative open/close methods marked as deprecated.
  • Refactor
    • Header state synchronized to external binding; demos and stories migrated from ref-based control to reactive two-way binding.
    • Removed certain globally declared components from type definitions.
  • Chores
    • .gitignore updated to ignore .cunzhi* files and folders.

@coderabbitai
Copy link

coderabbitai bot commented Sep 10, 2025

Walkthrough

Adds a new openHeader prop with v-model support to Sender and MentionSender for controlling header visibility; emits update:openHeader. Demos, docs (EN/ZH), and stories are updated to use reactive binding instead of imperative methods. Deprecates openHeader()/closeHeader() methods. Removes two global component typings. Adds a new .gitignore pattern.

Changes

Cohort / File(s) Summary
Git ignore
./.gitignore
Appends ignore pattern .cunzhi*.
Core: Sender header state (feature)
packages/core/src/components/Sender/index.vue
Adds prop openHeader, computed sync (internalHeaderOpen/headerOpenState), emits update:openHeader, replaces visiableHeader usage, keeps openHeader()/closeHeader() but marks deprecated.
Core: MentionSender header state (feature)
packages/core/src/components/MentionSender/index.vue
Mirrors Sender changes: new openHeader prop, internal sync, emits update:openHeader, template uses headerOpenState, deprecates openHeader()/closeHeader().
Core types: Sender
packages/core/src/components/Sender/types.d.ts
Adds openHeader?: boolean prop and update:openHeader emit signature.
Core types: MentionSender
packages/core/src/components/MentionSender/types.d.ts
Adds openHeader?: boolean prop and update:openHeader emit signature.
Global component typings
packages/core/components.d.ts
Removes ElInputNumber and IndexOri from Vue GlobalComponents.
Docs demos (EN)
apps/docs/en/components/sender/demos/header.vue, apps/docs/en/components/mentionSender/demos/header.vue
Switch demos to v-model:open-header with openHeader state; add deprecation notes; replace ref-based control with toggleHeader.
Docs API (EN)
apps/docs/en/components/sender/index.md, apps/docs/en/components/mentionSender/index.md
Document new prop openHeader (Boolean, default false) with v-model:openHeader.
Docs demos (ZH)
apps/docs/zh/components/sender/demos/header.vue, apps/docs/zh/components/mentionSender/demos/header.vue
Same as EN: use v-model:open-header, add deprecation guidance, simplify handlers.
Docs API (ZH)
apps/docs/zh/components/sender/index.md, apps/docs/zh/components/mentionSender/index.md
Add openHeader prop documentation with two-way binding note.
Stories: Sender
packages/core/src/stories/Sender/CustomSolt.vue, packages/core/src/stories/Sender/Sender.stories.ts
Bind v-model:open-header="openHeader", remove imperative calls; add story argTypes/args for openHeader.
Stories: MentionSender
packages/core/src/stories/MentionSender/CustomSolt.vue, packages/core/src/stories/MentionSender/MentionSender.stories.ts
Same as Sender stories: two-way binding and story props for openHeader.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Parent as Parent (Demo/Story)
  participant Comp as Sender / MentionSender

  Note over Parent,Comp: Two-way binding with v-model:openHeader

  User->>Parent: Click toggle
  Parent->>Parent: openHeader = !openHeader
  Parent->>Comp: prop openHeader updated
  Comp->>Comp: headerOpenState syncs internalHeaderOpen
  Comp-->>Parent: emit update:openHeader(openHeader)
  Note right of Comp: Header shown/hidden based on headerOpenState
Loading
sequenceDiagram
  autonumber
  participant Parent
  participant Comp as Sender / MentionSender

  rect rgba(255,235,205,0.4)
  Note over Parent,Comp: Deprecated path (still supported)
  Parent->>Comp: call openHeader() / closeHeader()
  Comp->>Comp: headerOpenState = true/false
  Comp-->>Parent: emit update:openHeader(value)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

A flick of the ear, a toggle with flair,
Headers now open by bindings we share.
No hutch of refs, no burrow of calls—
Just v-model whispers along the walls.
update:openHeader, thump-thump—approved!
This rabbit declares: the docs have moved. 🐇✨

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • 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.

@GBcui
Copy link
Author

GBcui commented Sep 10, 2025

Generate unit tests

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.

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (3)
packages/core/src/stories/Sender/CustomSolt.vue (1)

175-177: Missing icon import for (compile error).

<Link /> is used but not imported.

-import { CircleClose, Delete, Position } from '@element-plus/icons-vue';
+import { CircleClose, Delete, Position, Link } from '@element-plus/icons-vue';
packages/core/src/stories/MentionSender/CustomSolt.vue (1)

179-186: Missing icon import: is used but not imported.

This will fail at compile time. Import it from @element-plus/icons-vue.

-import { CircleClose, Delete, Position } from '@element-plus/icons-vue';
+import { CircleClose, Delete, Position, Link } from '@element-plus/icons-vue';
packages/core/src/components/Sender/index.vue (1)

1-585: Fix style lint errors in Sender component
There are 19 antfu/if-newline and style/brace-style violations in packages/core/src/components/Sender/index.vue; run

npx eslint --fix packages/core/src/components/Sender/index.vue

or manually adjust newline-after-if and brace placements to satisfy CI.

🧹 Nitpick comments (21)
.gitignore (1)

50-50: Clarify intent of .cunzhi ignore.*

If you intend to ignore only directories, add a trailing slash. If both files and dirs are intended, this is fine.

Optional tweak:

-.cunzhi*
+.cunzhi*/
packages/core/src/components/MentionSender/index.vue (4)

100-123: Emit only on actual state change to avoid redundant updates.

Guard the setter to prevent no-op emits and possible parent churn.

Apply:

 const headerOpenState = computed({
   get() {
     return internalHeaderOpen.value;
   },
   set(value) {
-    if (props.readOnly || props.disabled) return;
-
-    internalHeaderOpen.value = value;
-    // 始终触发更新事件,让外部可以监听状态变化
-    emits('update:openHeader', value);
+    if (props.readOnly || props.disabled) return;
+    if (internalHeaderOpen.value === value) return;
+    internalHeaderOpen.value = value;
+    emits('update:openHeader', value);
   }
 });

153-188: Use e.key === 'Enter' instead of deprecated keyCode.

KeyboardEvent.keyCode is deprecated; prefer key === 'Enter'. Also fix brace style at } else { to satisfy lint.

Apply:

-  if ('webkitSpeechRecognition' in window) {
+  if ('webkitSpeechRecognition' in window) {
     ...
-    recognition.value.start();
-  } else {
+    recognition.value.start();
+  }
+  else {
     console.error('浏览器不支持 Web Speech API');
   }

And later:

-  if (e.keyCode === 13) {
+  if (e.key === 'Enter') {
     e.preventDefault();
     if (props.submitType === 'enter') {
       _isComKeyDown ? _resetSelectionRange() : submit();
-    } else {
+    }
+    else {
       _isComKeyDown ? submit() : _resetSelectionRange();
     }
   }

52-59: Fix lint: newline-after-if and brace style.

ESLint errors (antfu/if-newline, style/brace-style) are from single-line if returns and } else { on the same line. Expand to multi-line and place else on a new line.

Apply pattern:

-    if (props.readOnly || props.disabled) return;
+    if (props.readOnly || props.disabled)
+      return;

And:

-  } else {
+  }
+  else {

Repeat for the highlighted lines to clear all reported lint errors.

Also applies to: 116-121, 130-136, 142-146, 153-156, 218-226, 230-231, 260-264, 280-286


206-226: Also respect disabled where actions are blocked.

A few handlers only check readOnly. Align with submit() by checking disabled too so the UI doesn’t react while disabled.

Apply:

 function cancel() {
-  if (props.readOnly) return;
+  if (props.readOnly || props.disabled)
+    return;
   emits('cancel', internalValue.value);
 }

 function clear() {
-  if (props.readOnly) return; // 直接返回,不执行后续逻辑
+  if (props.readOnly || props.disabled)
+    return; // 直接返回,不执行后续逻辑
   ...
 }

 function handleKeyDown(e: { target: HTMLTextAreaElement } & KeyboardEvent) {
-  if (props.readOnly) return; // 直接返回,不执行后续逻辑
+  if (props.readOnly || props.disabled)
+    return; // 直接返回,不执行后续逻辑
   ...
 }

 function focus(type = 'all') {
-  if (props.readOnly) {
+  if (props.readOnly || props.disabled) {
     return false;
   }
   ...
 }

Also applies to: 268-287

apps/docs/en/components/mentionSender/index.md (1)

145-145: Clarify binding notation (kebab-case in templates).

Use kebab-case for directive arguments in templates.

-| `openHeader`              | Boolean              | No       | false                      | Whether to open the custom header of the input box, using `v-model:openHeader` for two-way binding
+| `openHeader`              | Boolean              | No       | false                      | Whether to open the custom header; two-way bind via `v-model:open-header` in templates.
apps/docs/zh/components/mentionSender/index.md (1)

145-145: Unify binding notation and punctuation.

Prefer kebab-case and end the sentence with “。”.

-| `openHeader`              | Boolean              | 否       | false                      | 输入框自定义头部是否打开,使用 `v-model:openHeader` 进行双向绑定
+| `openHeader`              | Boolean              | 否       | false                      | 输入框自定义头部是否打开,使用 `v-model:open-header` 进行双向绑定。
apps/docs/en/components/sender/index.md (1)

103-103: Clarify binding notation (kebab-case in templates).

Use kebab-case for directive arguments in templates.

-| `openHeader`              | Boolean              | No       | false                      | Whether to open the custom header of the input box, using `v-model:openHeader` for two-way binding
+| `openHeader`              | Boolean              | No       | false                      | Whether to open the custom header; two-way bind via `v-model:open-header` in templates.
apps/docs/zh/components/sender/demos/header.vue (1)

15-22: Use kebab-case in the recommended snippet.

Match actual usage below to avoid confusion.

-<Sender v-model:openHeader="openHeader">
+<Sender v-model:open-header="openHeader">
packages/core/src/stories/MentionSender/CustomSolt.vue (2)

9-9: Comment casing: use kebab-case in docs/comments to match actual binding.

Change the comment to v-model:open-header for consistency with the template.

-const openHeader = ref(true); // 使用 v-model:openHeader 控制头部显示状态
+const openHeader = ref(true); // 使用 v-model:open-header 控制头部显示状态

124-124: Avoid
for layout spacing in stories.

Prefer semantic spacing via CSS/margins to keep markup clean.

-      <br />
+      <!-- spacing handled by CSS, e.g., .content > .btn-row { margin-bottom: 8px } -->

Also applies to: 139-139

apps/docs/en/components/sender/demos/header.vue (1)

30-30: Align comment with actual API.

Use v-model:open-header in the comment for consistency.

-const openHeader = ref(true); // Use v-model:openHeader to control header display state
+const openHeader = ref(true); // Use v-model:open-header to control header display state
packages/core/src/components/Sender/index.vue (6)

62-65: Block internal model updates when readOnly/disabled.

Good guard; consider formatting to satisfy lint (if-newline).

-    if (props.readOnly || props.disabled) return;
+    if (props.readOnly || props.disabled)
+      return;

92-95: Same guard for popover visibility is appropriate.

Also apply newline style to pass lint.

-    if (props.readOnly || props.disabled) return;
+    if (props.readOnly || props.disabled)
+      return;

100-158: Trigger watcher: remove unnecessary deep option for string; minor perf/readability.

-watch(
+watch(
   () => internalValue.value,
   (newVal, oldVal) => {
-    if (isComposing.value) return;
+    if (isComposing.value)
+      return;
     ...
-  },
-  { deep: true, immediate: true }
+  },
+  { immediate: true }
 )

301-336: Key handling respects readOnly and submitType; lint nits only.

Functionally good. Consider fixing brace-style and if-newline to satisfy the linter.

-    if (props.submitType === 'enter') {
-      _isComKeyDown ? _resetSelectionRange() : submit();
-    } else {
-      _isComKeyDown ? submit() : _resetSelectionRange();
-    }
+    if (props.submitType === 'enter') {
+      _isComKeyDown ? _resetSelectionRange() : submit();
+    }
+    else {
+      _isComKeyDown ? submit() : _resetSelectionRange();
+    }

446-450: Don’t render header wrapper when there’s no header slot.

Avoid empty wrapper affecting layout if openHeader=true without a slot.

-        <div v-if="headerOpenState" class="el-sender-header-wrap">
+        <div v-if="headerOpenState && $slots.header" class="el-sender-header-wrap">
           <div v-if="$slots.header" class="el-sender-header">
             <slot name="header" />
           </div>
         </div>

200-207: Confirm deprecation of openHeader() in types & code. SenderEmits includes 'update:openHeader' (types.d.ts:60, index.vue:191) and openHeader is marked @deprecated in index.vue (lines 197 & 211). Consider updating any external/docs (e.g. README) to note this deprecation.

apps/docs/zh/components/mentionSender/demos/header.vue (1)

9-9: Prefer kebab-case in docs: v-model:open-header

Use kebab-case in templates to match Vue style and your actual demo usage.

-以下方法将在下个大版本中移除,推荐使用 `v-model:openHeader` 进行双向绑定控制:
+以下方法将在下个大版本中移除,推荐使用 `v-model:open-header` 进行双向绑定控制:
-使用 `v-model:openHeader` 进行双向绑定控制头部显示状态:
+使用 `v-model:open-header` 进行双向绑定控制头部显示状态:

Also applies to: 16-16

apps/docs/en/components/mentionSender/demos/header.vue (2)

19-22: Unify snippet with actual usage: use kebab-case argument

Match the demo’s v-model:open-header to avoid confusing readers.

-<MentionSender v-model:openHeader="openHeader">
+<MentionSender v-model:open-header="openHeader">
   <template #header>Header content</template>
 </MentionSender>

9-9: Docs phrasing: prefer v-model:open-header in templates

Minor consistency fix with Vue template conventions and your demo.

-It is recommended to use `v-model:openHeader` for two-way binding control:
+It is recommended to use `v-model:open-header` for two-way binding control:
-Use `v-model:openHeader` for two-way binding to control header display state:
+Use `v-model:open-header` for two-way binding to control header display state:

Also applies to: 16-16

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3ce64d and ab4a5e4.

📒 Files selected for processing (18)
  • .gitignore (1 hunks)
  • apps/docs/en/components/mentionSender/demos/header.vue (2 hunks)
  • apps/docs/en/components/mentionSender/index.md (1 hunks)
  • apps/docs/en/components/sender/demos/header.vue (2 hunks)
  • apps/docs/en/components/sender/index.md (1 hunks)
  • apps/docs/zh/components/mentionSender/demos/header.vue (2 hunks)
  • apps/docs/zh/components/mentionSender/index.md (1 hunks)
  • apps/docs/zh/components/sender/demos/header.vue (2 hunks)
  • apps/docs/zh/components/sender/index.md (1 hunks)
  • packages/core/components.d.ts (0 hunks)
  • packages/core/src/components/MentionSender/index.vue (10 hunks)
  • packages/core/src/components/MentionSender/types.d.ts (2 hunks)
  • packages/core/src/components/Sender/index.vue (15 hunks)
  • packages/core/src/components/Sender/types.d.ts (2 hunks)
  • packages/core/src/stories/MentionSender/CustomSolt.vue (5 hunks)
  • packages/core/src/stories/MentionSender/MentionSender.stories.ts (2 hunks)
  • packages/core/src/stories/Sender/CustomSolt.vue (5 hunks)
  • packages/core/src/stories/Sender/Sender.stories.ts (3 hunks)
💤 Files with no reviewable changes (1)
  • packages/core/components.d.ts
🧰 Additional context used
🧬 Code graph analysis (5)
packages/core/src/components/Sender/types.d.ts (1)
packages/core/src/components/EditorSender/types.d.ts (2)
  • EditorProps (13-30)
  • EditorSenderEmits (73-82)
packages/core/src/components/MentionSender/types.d.ts (2)
packages/core/src/components/EditorSender/types.d.ts (2)
  • EditorProps (13-30)
  • EditorSenderEmits (73-82)
packages/core/src/components/Conversations/types.d.ts (1)
  • ConversationsEmits (101-109)
packages/core/src/stories/Sender/Sender.stories.ts (1)
packages/core/src/stories/EditorSender/EditorSender.stories.ts (2)
  • setup (106-110)
  • _args (105-116)
apps/docs/en/components/sender/index.md (1)
packages/core/src/components/EditorSender/types.d.ts (1)
  • EditorProps (13-30)
apps/docs/zh/components/sender/index.md (1)
packages/core/src/components/EditorSender/types.d.ts (1)
  • EditorProps (13-30)
🪛 ESLint
packages/core/src/components/MentionSender/index.vue

[error] 57-57: Expect newline after if

(antfu/if-newline)


[error] 116-116: Expect newline after if

(antfu/if-newline)


[error] 130-130: Expect newline after if

(antfu/if-newline)


[error] 132-132: Expect newline after if

(antfu/if-newline)


[error] 143-143: Expect newline after if

(antfu/if-newline)


[error] 144-144: Expect newline after if

(antfu/if-newline)


[error] 154-154: Expect newline after if

(antfu/if-newline)


[error] 185-185: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 218-218: Expect newline after if

(antfu/if-newline)


[error] 223-223: Expect newline after if

(antfu/if-newline)


[error] 230-230: Expect newline after if

(antfu/if-newline)


[error] 261-261: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 282-282: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 284-284: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)

packages/core/src/components/Sender/index.vue

[error] 62-62: Expect newline after if

(antfu/if-newline)


[error] 92-92: Expect newline after if

(antfu/if-newline)


[error] 104-104: Expect newline after if

(antfu/if-newline)


[error] 123-123: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 137-137: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 152-152: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 187-187: Expect newline after if

(antfu/if-newline)


[error] 201-201: Expect newline after if

(antfu/if-newline)


[error] 203-203: Expect newline after if

(antfu/if-newline)


[error] 214-214: Expect newline after if

(antfu/if-newline)


[error] 215-215: Expect newline after if

(antfu/if-newline)


[error] 225-225: Expect newline after if

(antfu/if-newline)


[error] 256-256: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 289-289: Expect newline after if

(antfu/if-newline)


[error] 294-294: Expect newline after if

(antfu/if-newline)


[error] 301-301: Expect newline after if

(antfu/if-newline)


[error] 332-332: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 353-353: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 355-355: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)

🔇 Additional comments (25)
packages/core/src/components/Sender/types.d.ts (1)

25-27: LGTM: prop + v-model event shape are consistent.

openHeader?: boolean and update:openHeader align with Vue v-model conventions and mirror MentionSender.

Also applies to: 60-60

packages/core/src/components/MentionSender/types.d.ts (1)

32-34: LGTM: public API matches Sender and supports v-model.

The prop and event are correctly named and typed for two-way binding.

Also applies to: 58-58

packages/core/src/components/MentionSender/index.vue (1)

335-348: Confirm no conflict between exposed method name and prop name.

Exposing openHeader while also having a prop named openHeader is usually safe in <script setup> (expose controls the ref surface), but please confirm no tools/types rely on reading props via template refs. If necessary, alias exposed methods while keeping deprecated names for BC.

packages/core/src/stories/MentionSender/MentionSender.stories.ts (2)

22-29: Hiding openHeader from controls makes sense here.

Keeping it disabled in Controls to avoid confusion with the CustomSolt example is fine.


181-191: Add missing imports for ref/watch (unless auto-import is configured).

This file uses ref/watch without explicit imports; add them if auto-import isn’t enabled in Storybook.

+import { ref, watch } from 'vue';
apps/docs/zh/components/sender/demos/header.vue (1)

8-13: Good deprecation notice.

Clear guidance toward v-model is appreciated.

packages/core/src/stories/Sender/Sender.stories.ts (1)

22-29: Arg wiring looks fine.

ArgTypes and default args.openHeader = false are consistent.

Also applies to: 146-146

packages/core/src/stories/Sender/CustomSolt.vue (2)

10-11: OK to toggle via external state.

The move to openHeader state with v-model aligns with the new API.


14-21: Also import onMounted/ref/computed if auto-import isn’t active.

These are used (onMounted, ref, computed) but not imported here.

-import { onUnmounted } from 'vue';
+import { ref, computed, onMounted, onUnmounted } from 'vue';
packages/core/src/stories/MentionSender/CustomSolt.vue (3)

40-45: LGTM: reactive toggle replaces imperative API cleanly.

Toggling via local state aligns with the new v-model contract and keeps back-compat methods unused here.


143-143: No action required: v-model:open-header binding is correct. MentionSender declares an openHeader prop (in types.d.ts) and emits update:openHeader (in index.vue), matching Sender’s API.


1-8: Auto-import plugin present in docs config. Vue APIs (ref, computed, onMounted, onBeforeUnmount, nextTick) are auto-imported via apps/docs/vite.config.mts, so explicit imports in CustomSolt.vue aren’t needed.

apps/docs/en/components/sender/demos/header.vue (4)

8-13: Deprecation note is clear.

Good call-out of the legacy methods and the v-model alternative.


32-38: LGTM: simple, readable state toggling.


51-55: LGTM: UX toggle label reflects state; binding uses v-model:open-header correctly.


58-67: LGTM: header slot content and close action demonstrate API well.

packages/core/src/components/Sender/index.vue (5)

29-31: Prop default looks right.

openHeader defaulting to false is sensible and backwards-compatible.


171-193: State bridge for v-model is solid; emits keep parent in sync.

Nice separation (internalHeaderOpen + computed setter).


214-217: Deprecated closeHeader() retained appropriately.

Matches the new state bridge; fine.


225-256: readOnly short-circuit in voice flow prevents accidental side effects.


289-297: Guarded cancel/clear respect readOnly; good.

apps/docs/zh/components/mentionSender/demos/header.vue (2)

51-55: LGTM: toggle + v-model wiring is correct

Button toggles state and binding uses v-model:open-header consistently with component API.


30-30: No explicit ref import required
AutoImport in apps/docs/vite.config.mts has imports: ['vue'], which auto-imports Vue APIs including ref.

apps/docs/en/components/mentionSender/demos/header.vue (2)

51-55: LGTM: binding and slot usage look good

Demo correctly exercises two-way binding and header slot.


30-30: Auto-import of ref is already configured
The unplugin-auto-import plugin in apps/docs/vite.config.mts includes imports: ['vue'], so ref is available without an explicit import.

Comment on lines +15 to +22
::: tip Recommended Usage
Use `v-model:openHeader` for two-way binding to control header display state:

```vue
<Sender v-model:openHeader="openHeader">
<template #header>Header content</template>
</Sender>
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix sample: use kebab-case argument in DOM templates.

In SFC/DOM templates, the v-model argument must be kebab-cased. Update the snippet.

-```vue
-<Sender v-model:openHeader="openHeader">
+```vue
+<Sender v-model:open-header="openHeader">
   <template #header>Header content</template>
 </Sender>

<details>
<summary>🤖 Prompt for AI Agents</summary>

In apps/docs/en/components/sender/demos/header.vue around lines 15 to 22, the
example uses a camelCase v-model argument (v-model:openHeader) which is invalid
in SFC/DOM templates; update the snippet to use kebab-case for the v-model
argument (v-model:open-header="openHeader") in the template example so it
follows Vue's DOM/SFC template requirements.


</details>

<!-- fingerprinting:phantom:medusa:chinchilla -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +19 to +22
<Sender v-model:openHeader="openHeader">
<template #header>头部内容</template>
</Sender>
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix component tag and use kebab-case v-model arg in the snippet

This demo is for MentionSender but the snippet shows Sender and camelCase argument. Align with actual usage below.

Apply:

-<Sender v-model:openHeader="openHeader">
-  <template #header>头部内容</template>
-</Sender>
+<MentionSender v-model:open-header="openHeader">
+  <template #header>头部内容</template>
+</MentionSender>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Sender v-model:openHeader="openHeader">
<template #header>头部内容</template>
</Sender>
```
<MentionSender v-model:open-header="openHeader">
<template #header>头部内容</template>
</MentionSender>
🤖 Prompt for AI Agents
In apps/docs/zh/components/mentionSender/demos/header.vue around lines 19 to 22,
the demo snippet incorrectly uses <Sender> and a camelCase v-model argument;
update the component tag to MentionSender and change the v-model argument to
kebab-case (v-model:open-header) so it matches the actual component API and the
usage shown elsewhere; ensure the slot template remains the same (template
#header) and that the binding syntax is consistent with other examples.

| ------------------------- | -------------------- | -------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `v-model` | String || '' | 输入框的绑定值,使用 `v-model` 进行双向绑定。 |
| `placeholder` | String || '' | 输入框的提示语文本。 |
| `openHeader` | Boolean || false | 输入框自定义头部是否打开,使用 `v-model:openHeader` 进行双向绑定本。 |
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo and prefer kebab-case for v-model arg.

Remove the stray “本” and use kebab-case in template-facing docs.

-| `openHeader`              | Boolean              | 否       | false                      | 输入框自定义头部是否打开,使用 `v-model:openHeader` 进行双向绑定本。 
+| `openHeader`              | Boolean              | 否       | false                      | 输入框自定义头部是否打开,使用 `v-model:open-header` 进行双向绑定。
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| `openHeader` | Boolean || false | 输入框自定义头部是否打开,使用 `v-model:openHeader` 进行双向绑定本。 |
| `openHeader` | Boolean || false | 输入框自定义头部是否打开,使用 `v-model:open-header` 进行双向绑定。 |
🤖 Prompt for AI Agents
In apps/docs/zh/components/sender/index.md around line 103, the table cell has a
stray Chinese character "本" and uses camelCase for the v-model arg; remove the
stray "本" and change the example to use kebab-case for the template-facing
v-model binding (v-model:open-header) so the sentence reads without the extra
character and shows the preferred kebab-case usage.

Comment on lines +124 to 146
/**
* 打开头部容器
* @deprecated 此方法将在下个大版本中移除,请使用 v-model:openHeader 代替
* @returns {boolean} 是否成功打开
*/
function openHeader() {
if (!slots.header)
return false;
if (!slots.header) return false;
if (props.readOnly)
return false;
if (props.readOnly) return false;
visiableHeader.value = true;
headerOpenState.value = true;
return true;
}
/**
* 关闭头部容器
* @deprecated 此方法将在下个大版本中移除,请使用 v-model:openHeader 代替
*/
function closeHeader() {
if (!slots.header)
return;
if (props.readOnly)
return;
visiableHeader.value = false;
if (!slots.header) return;
if (props.readOnly) return;
headerOpenState.value = false;
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Honor disabled state in methods and make return behavior consistent.

openHeader() should also respect disabled. closeHeader() should return a boolean or document it returns void; currently it silently no-ops when disabled and always succeeds when disabled via setter guard. Suggest returning booleans for both while keeping deprecated API.

Apply:

 function openHeader() {
-  if (!slots.header) return false;
-  if (props.readOnly) return false;
+  if (!slots.header) return false;
+  if (props.readOnly || props.disabled) return false;
   headerOpenState.value = true;
   return true;
 }
 
 /**
  * 关闭头部容器
  * @deprecated 此方法将在下个大版本中移除,请使用 v-model:openHeader 代替
  */
 function closeHeader() {
-  if (!slots.header) return;
-  if (props.readOnly) return;
-  headerOpenState.value = false;
+  if (!slots.header) return false;
+  if (props.readOnly || props.disabled) return false;
+  headerOpenState.value = false;
+  return true;
 }

If changing closeHeader’s return type is not acceptable for compatibility, keep void but still add the disabled guard and update docs accordingly.


🏁 Script executed:

#!/bin/bash
# Locate props definitions and check for disabled prop in MentionSender component
grep -n "defineProps" packages/core/src/components/MentionSender/index.vue || true
grep -n "props\\s*:" packages/core/src/components/MentionSender/index.vue || true
grep -n "disabled" packages/core/src/components/MentionSender/index.vue || true

# Show the openHeader/closeHeader methods for context
sed -n '120,160p' packages/core/src/components/MentionSender/index.vue

Length of output: 1372


Ensure props.disabled is checked and return behavior aligned in header methods

  • In packages/core/src/components/MentionSender/index.vue’s openHeader and closeHeader, add props.disabled to the early-return guard.
  • Make closeHeader return a boolean (with @returns {boolean}) to match openHeader, or if that breaks compatibility, retain its void signature but update its JSDoc to note it returns void while still honoring the disabled check.
🧰 Tools
🪛 ESLint

[error] 130-130: Expect newline after if

(antfu/if-newline)


[error] 132-132: Expect newline after if

(antfu/if-newline)


[error] 143-143: Expect newline after if

(antfu/if-newline)


[error] 144-144: Expect newline after if

(antfu/if-newline)

🤖 Prompt for AI Agents
In packages/core/src/components/MentionSender/index.vue around lines 124 to 146,
the openHeader/closeHeader methods currently skip checking props.disabled and
closeHeader returns void while openHeader returns boolean; update both methods
to early-return when props.disabled is true (in the same way they already check
props.readOnly) and make closeHeader return a boolean to match openHeader
(return false on early exits and true when it actually closes the header), or if
you must preserve the void signature for compatibility, leave closeHeader's
signature as void but update its JSDoc to @returns {void} and still add the
props.disabled guard so it honors the disabled state.

Comment on lines +204 to 206
v-model:openHeader="openHeader"
v-model:triggerPopoverVisible="triggerVisible"
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Bug: v-model bound to undefined openHeader.

openHeader isn’t defined in setup(), causing a runtime error. Define it and sync with args; also import ref/watch if auto-import isn’t enabled.

+import { ref, watch } from 'vue';
@@
     setup() {
-      const model = ref(args.modelValue);
-      const triggerVisible = ref(args.triggerPopoverVisible);
+      const model = ref(args.modelValue);
+      const triggerVisible = ref(args.triggerPopoverVisible);
+      const openHeader = ref(args.openHeader);
@@
       watch(triggerVisible, val => {
         args.triggerPopoverVisible = val;
       });
+      watch(openHeader, val => {
+        args.openHeader = val;
+      });
@@
-        triggerVisible
+        triggerVisible,
+        openHeader
       };
     },
@@
-        v-model:openHeader="openHeader"
+        v-model:openHeader="openHeader"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
v-model:openHeader="openHeader"
v-model:triggerPopoverVisible="triggerVisible"
/>
// ← at the top of the file, alongside your other imports
import { ref, watch } from 'vue';
// …
export const Default: StoryFn = (args) => ({
components: { Sender },
setup() {
const model = ref(args.modelValue);
const triggerVisible = ref(args.triggerPopoverVisible);
const openHeader = ref(args.openHeader);
watch(model, val => {
args.modelValue = val;
});
watch(triggerVisible, val => {
args.triggerPopoverVisible = val;
});
watch(openHeader, val => {
args.openHeader = val;
});
return {
args,
model,
triggerVisible,
openHeader
};
},
template: `
<Sender
v-model:modelValue="model"
v-model:openHeader="openHeader"
v-model:triggerPopoverVisible="triggerVisible"
/>
`
});
🤖 Prompt for AI Agents
In packages/core/src/stories/Sender/Sender.stories.ts around lines 204-206, the
template binds v-model:openHeader to an undefined openHeader which causes a
runtime error; define openHeader in setup() as a reactive ref, import ref (and
watch if not auto-imported), initialize it from args (e.g.,
ref(Boolean(args.openHeader))) and set up a watch to keep args and openHeader in
sync (or update args when openHeader changes) so the v-model has a defined
reactive variable.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant