Skip to content

feat(ChatMessages): expose registerMessageRef#6275

Open
zAlweNy26 wants to merge 3 commits intonuxt:v4from
zAlweNy26:feat/expose-message-ref
Open

feat(ChatMessages): expose registerMessageRef#6275
zAlweNy26 wants to merge 3 commits intonuxt:v4from
zAlweNy26:feat/expose-message-ref

Conversation

@zAlweNy26
Copy link
Copy Markdown
Contributor

🔗 Linked issue

❓ Type of change

  • 📖 Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

To be able to reuse the scroll logic even when the default slot is used

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@github-actions github-actions Bot added the v4 #4488 label Mar 31, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

The ChatMessages component now exposes an internal method registerMessageRef(id: string, element: ComponentPublicInstance | null): void via defineExpose, and passes it into the default slot as a required slot prop. The component's slot typings were updated to require a registerMessageRef prop. Documentation was updated with an "Expose" section documenting the registerMessageRef method and its signature.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: exposing the registerMessageRef method from the ChatMessages component.
Description check ✅ Passed The description explains the purpose of the change (reusing scroll logic when the default slot is used) and confirms documentation has been updated accordingly.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

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

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
Copy Markdown
Contributor

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/content/docs/2.components/chat-messages.md`:
- Line 448: The table cell for the `registerMessageRef` signature is broken by
the unescaped union pipe in `ComponentPublicInstance | null`; update the table
entry for `registerMessageRef(id: string, element: ComponentPublicInstance |
null)` to escape the pipe (e.g., `ComponentPublicInstance \| null`) so the `|`
is not treated as a Markdown column separator and the table renders correctly.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 14812679-c85d-4832-a30b-2ea371b946c8

📥 Commits

Reviewing files that changed from the base of the PR and between ef5959f and 6c69f16.

📒 Files selected for processing (2)
  • docs/content/docs/2.components/chat-messages.md
  • src/runtime/components/ChatMessages.vue

Comment thread docs/content/docs/2.components/chat-messages.md Outdated
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 31, 2026

npm i https://pkg.pr.new/@nuxt/ui@6275

commit: 4f1fd8e

zAlweNy26 and others added 3 commits April 11, 2026 15:51
@zAlweNy26 zAlweNy26 force-pushed the feat/expose-message-ref branch from d1913ee to 4f1fd8e Compare April 11, 2026 13:52
Copy link
Copy Markdown
Contributor

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/runtime/components/ChatMessages.vue`:
- Line 70: The slot prop type for registerMessageRef is too narrow and the ref
cleanup is missing; update the slot signature for default (and the other
occurrence referenced) so registerMessageRef accepts Element |
ComponentPublicInstance | null, and modify the implementation of
registerMessageRef (the function that currently stores refs in the message refs
map around the code handling lines ~127–132 and the similar block at ~319) to
delete the map entry when the callback receives null (i.e., on unmount) instead
of leaving stale entries; ensure you update both the type declarations and the
runtime logic that adds/removes entries in the refs map (refer to
registerMessageRef and the message refs map usage).
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e34604dd-809a-455b-8542-74a84f20f6d7

📥 Commits

Reviewing files that changed from the base of the PR and between d1913ee and 4f1fd8e.

📒 Files selected for processing (2)
  • docs/content/docs/2.components/chat-messages.md
  • src/runtime/components/ChatMessages.vue
✅ Files skipped from review due to trivial changes (1)
  • docs/content/docs/2.components/chat-messages.md

[K in keyof ChatMessageSlots]?: ExtendSlotWithVersion<K>
} & {
default?(props?: {}): VNode[]
default?(props: { registerMessageRef: (id: string, element: ComponentPublicInstance | null) => void }): VNode[]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

In Vue 3.5 template ref callbacks (:ref="fn"), what argument types are passed for native HTML elements and for component refs? Is null passed on unmount?

💡 Result:

In Vue 3.5 (and earlier Vue 3 versions), template ref callbacks bound via :ref="fn" receive a single argument: - For native HTML elements: the DOM Element instance (e.g., HTMLInputElement). - For component refs: the component public instance (ComponentPublicInstance). Yes, null is passed to the callback when the element/component is unmounted. This behavior is unchanged in Vue 3.5, which primarily introduced useTemplateRef for string-based refs but retains function ref support as before.

Citations:


🏁 Script executed:

# Check the ChatMessages.vue file for the relevant code sections
cat -n src/runtime/components/ChatMessages.vue | sed -n '65,75p'

Repository: nuxt/ui

Length of output: 524


🏁 Script executed:

# Check the registerMessageRef implementation
cat -n src/runtime/components/ChatMessages.vue | sed -n '125,135p'

Repository: nuxt/ui

Length of output: 433


🏁 Script executed:

# Check the slot binding at line 319
cat -n src/runtime/components/ChatMessages.vue | sed -n '315,325p'

Repository: nuxt/ui

Length of output: 665


🏁 Script executed:

# Verify file structure - count lines to ensure line numbers are valid
wc -l src/runtime/components/ChatMessages.vue

Repository: nuxt/ui

Length of output: 94


Broaden registerMessageRef to handle native refs and cleanup unmounted entries.

Line 70 currently constrains the slot callback to ComponentPublicInstance, but Vue 3 template ref callbacks also receive native Element instances. Additionally, the current implementation at lines 127–132 does not delete stale entries when ref callbacks receive null on unmount. When custom default-slot markup uses native element refs, this can cause type mismatches and retain stale map entries.

Widen the type to Element | ComponentPublicInstance | null and add cleanup logic:

Suggested patch
 export type ChatMessagesSlots = {
   [K in keyof ChatMessageSlots]?: ExtendSlotWithVersion<K>
 } & {
-  default?(props: { registerMessageRef: (id: string, element: ComponentPublicInstance | null) => void }): VNode[]
+  default?(props: { registerMessageRef: (id: string, element: Element | ComponentPublicInstance | null) => void }): VNode[]
   indicator?(props: { ui: ChatMessages['ui'] }): VNode[]
   viewport?(props: { ui: ChatMessages['ui'], onClick: () => void }): VNode[]
 }
-function registerMessageRef(id: string, element: ComponentPublicInstance | null) {
-  const elInstance = element?.$el
-  if (elInstance) {
-    messagesRefs.value.set(id, elInstance)
-  }
-}
+function registerMessageRef(id: string, element: Element | ComponentPublicInstance | null) {
+  if (!element) {
+    messagesRefs.value.delete(id)
+    return
+  }
+
+  const elInstance = '$el' in element ? element.$el : element
+  if (elInstance instanceof HTMLElement) {
+    messagesRefs.value.set(id, elInstance)
+  }
+}

Also applies to: 319-319

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

In `@src/runtime/components/ChatMessages.vue` at line 70, The slot prop type for
registerMessageRef is too narrow and the ref cleanup is missing; update the slot
signature for default (and the other occurrence referenced) so
registerMessageRef accepts Element | ComponentPublicInstance | null, and modify
the implementation of registerMessageRef (the function that currently stores
refs in the message refs map around the code handling lines ~127–132 and the
similar block at ~319) to delete the map entry when the callback receives null
(i.e., on unmount) instead of leaving stale entries; ensure you update both the
type declarations and the runtime logic that adds/removes entries in the refs
map (refer to registerMessageRef and the message refs map usage).

:style="{ '--last-message-height': `${lastMessageHeight}px` }"
>
<slot>
<slot :register-message-ref="registerMessageRef">
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we really need to expose this in default slot? Isn't it enough to access it through a template ref? 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Personally, I’d prefer to avoid creating a template ref every time I need one when I’m dealing with simpler cases. I see the template ref as necessary for more complex scenarios.

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

Labels

v4 #4488

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants