| name | n-message |
| description | Message component for displaying toast notifications and feedback. Invoke when user needs to show temporary feedback messages, loading states, or success/error notifications in Naive UI. |
| metadata | {"author":"jiaiyan","version":"1.0.0"} |
Naive UI Message Component
Message component for displaying toast notifications and feedback messages at the top of the viewport.
When to Use
Use this component when:
- Operation feedback: Show success or error messages after user actions
- Loading states: Display loading indicators during async operations
- Notifications: Show temporary informational messages
- Validation feedback: Display form validation results
When to Invoke
Invoke this skill when:
- User needs to display toast messages programmatically
- User wants to use imperative API with useMessage
- User needs to customize message duration or closability
- User wants to modify existing messages dynamically
- User asks about message provider setup
Features
- Multiple Types: info, success, warning, error, loading
- Imperative API: Create messages programmatically with useMessage
- Custom Duration: Control how long messages display
- Closable: Optional close button
- Hover to Keep: Keep message alive on hover
- Custom Icons: Support for custom icons
- Multiple Placements: top, bottom, left, right variants
- Dynamic Updates: Modify messages after creation
API Reference
MessageProvider Props
| Name | Type | Default | Description |
|---|
| closable | boolean | false | Whether to show close icon on all messages. |
| container-class | string | undefined | Message container class. |
| container-style | string | CSSProperties | undefined | Message container style. |
| duration | number | 3000 | Default duration of on all messages. |
| keep-alive-on-hover | boolean | false | Whether to destroy while hovering on all messages. |
| max | number | undefined | Limit the number of messages to display. |
| placement | 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right' | 'top' | Placement of all messages. |
| to | string | HTMLElement | 'body' | Container node of message container. |
useMessage API
| Name | Type | Description |
|---|
| destroyAll | () => void | Destroy all popup messages. |
| create | (content: string | (() => VNodeChild), option?: MessageOption) => MessageReactive | Use create type message. |
| error | (content: string | (() => VNodeChild), option?: MessageOption) => MessageReactive | Use error type message. |
| info | (content: string | (() => VNodeChild), option?: MessageOption) => MessageReactive | Use info type message. |
| loading | (content: string | (() => VNodeChild), option?: MessageOption) => MessageReactive | Use loading type message. |
| success | (content: string | (() => VNodeChild), option?: MessageOption) => MessageReactive | Use success type message. |
| warning | (content: string | (() => VNodeChild), option?: MessageOption) => MessageReactive | Use warning type message. |
MessageOption Properties
| Name | Type | Description |
|---|
| closable | boolean | Whether to show close icon. |
| duration | number | The duration of the message. |
| icon | () => VNodeChild | Message icon. |
| keepAliveOnHover | boolean | Messages whether to destroy while hover. |
| render | MessageRenderMessage | Render function of the entire message. |
| showIcon | boolean | Whether to show icon. |
| type | 'info' | 'success' | 'warning' | 'error' | 'loading' | 'default' | Message type. |
| onAfterLeave | () => void | Callback after message disappeared. |
| onClose | () => void | Callback when close icon is clicked. |
| onLeave | () => void | Callback when message start to disappear. |
MessageReactive Properties
| Name | Type | Description |
|---|
| closable | boolean | Whether to show close icon. |
| content | string | (() => VNodeChild) | Message content. |
| destroy | () => void | Message destroy method. |
| icon | () => VNodeChild | Message icon. |
| keepAliveOnHover | boolean | Messages whether to destroy while hover. |
| showIcon | boolean | Whether to show icon. |
| type | 'info' | 'success' | 'warning' | 'error' | 'loading' | 'default' | Message type. |
| onAfterLeave | () => void | Callback after message disappeared. |
| onLeave | () => void | Callback when message start to disappear. |
MessageReactive Methods
| Name | Type | Description |
|---|
| destroy | () | Message destroy method. |
Basic Usage
Setup with MessageProvider
<!-- App.vue -->
<template>
<n-message-provider>
<Content />
</n-message-provider>
</template>
Basic Message Types
<template>
<n-space>
<n-button @click="showInfo">Info</n-button>
<n-button @click="showSuccess">Success</n-button>
<n-button @click="showWarning">Warning</n-button>
<n-button @click="showError">Error</n-button>
<n-button @click="showLoading">Loading</n-button>
</n-space>
</template>
<script setup>
import { useMessage } from 'naive-ui'
const message = useMessage()
const showInfo = () => message.info('This is an info message')
const showSuccess = () => message.success('Operation completed successfully')
const showWarning = () => message.warning('Please review before proceeding')
const showError = () => message.error('Something went wrong')
const showLoading = () => message.loading('Loading...')
</script>
Custom Duration
<template>
<n-button @click="showMessage">5 Second Message</n-button>
</template>
<script setup>
import { useMessage } from 'naive-ui'
const message = useMessage()
const showMessage = () => {
message.info('This message lasts 5 seconds', { duration: 5000 })
}
</script>
Closable Message
<template>
<n-button @click="showMessage">Closable Message</n-button>
</template>
<script setup>
import { useMessage } from 'naive-ui'
const message = useMessage()
const showMessage = () => {
message.info('Click X to close', { closable: true })
}
</script>
Keep Alive on Hover
<template>
<n-button @click="showMessage">Hover to Keep</n-button>
</template>
<script setup>
import { useMessage } from 'naive-ui'
const message = useMessage()
const showMessage = () => {
message.info('Hover over me to keep alive', { keepAliveOnHover: true })
}
</script>
Custom Icon
<template>
<n-button @click="showMessage">Custom Icon</n-button>
</template>
<script setup>
import { h } from 'vue'
import { useMessage, NIcon } from 'naive-ui'
const message = useMessage()
const showMessage = () => {
message.info('Custom icon message', {
icon: () => h(NIcon, null, () => '🔔')
})
}
</script>
No Icon
<template>
<n-button @click="showMessage">No Icon</n-button>
</template>
<script setup>
import { useMessage } from 'naive-ui'
const message = useMessage()
const showMessage = () => {
message.info('Message without icon', { showIcon: false })
}
</script>
Modify Existing Message
<template>
<n-space>
<n-button @click="createMessage">Create</n-button>
<n-button @click="changeType">Change Type</n-button>
<n-button @click="plus">Plus 1</n-button>
</n-space>
</template>
<script setup>
import { ref } from 'vue'
import { useMessage } from 'naive-ui'
const message = useMessage()
const msg = ref(null)
const count = ref(0)
const createMessage = () => {
count.value = 0
msg.value = message.info(`Count: ${count.value}`, { duration: 0 })
}
const changeType = () => {
if (msg.value) {
msg.value.type = msg.value.type === 'info' ? 'success' : 'info'
}
}
const plus = () => {
if (msg.value) {
count.value++
msg.value.content = `Count: ${count.value}`
}
}
</script>
Manually Close
<template>
<n-space>
<n-button @click="createMessage">Create</n-button>
<n-button @click="removeMessage">Destroy</n-button>
</n-space>
</template>
<script setup>
import { ref } from 'vue'
import { useMessage } from 'naive-ui'
const message = useMessage()
const msg = ref(null)
const createMessage = () => {
msg.value = message.loading('Loading...', { duration: 0 })
}
const removeMessage = () => {
if (msg.value) {
msg.value.destroy()
msg.value = null
}
}
</script>
Multiple Line Content
<template>
<n-button @click="showMessage">Multiple Lines</n-button>
</template>
<script setup>
import { useMessage } from 'naive-ui'
const message = useMessage()
const showMessage = () => {
message.info('Line 1\nLine 2\nLine 3')
}
</script>
Custom Placement
<template>
<n-message-provider placement="bottom">
<Content />
</n-message-provider>
</template>
Destroy All Messages
<template>
<n-button @click="clearAll">Clear All Messages</n-button>
</template>
<script setup>
import { useMessage } from 'naive-ui'
const message = useMessage()
const clearAll = () => {
message.destroyAll()
}
</script>
Common Patterns
Async Operation with Loading
<template>
<n-button @click="handleAsync">Submit</n-button>
</template>
<script setup>
import { useMessage } from 'naive-ui'
const message = useMessage()
const handleAsync = async () => {
const msg = message.loading('Submitting...', { duration: 0 })
try {
await new Promise(resolve => setTimeout(resolve, 2000))
msg.destroy()
message.success('Submitted successfully')
} catch (error) {
msg.destroy()
message.error('Submission failed')
}
}
</script>
Form Submission Feedback
<template>
<n-form @submit="handleSubmit">
<n-button type="primary" attr-type="submit">Submit Form</n-button>
</n-form>
</template>
<script setup>
import { useMessage } from 'naive-ui'
const message = useMessage()
const handleSubmit = async () => {
const msg = message.loading('Processing...', { duration: 0 })
try {
await submitForm()
msg.destroy()
message.success('Form submitted successfully!')
} catch (error) {
msg.destroy()
message.error(error.message || 'Submission failed')
}
}
</script>
Global Message (Outside Setup)
<!-- content.vue -->
<template>
<!-- content -->
</template>
<script setup>
import { useMessage } from 'naive-ui'
window.$message = useMessage()
</script>
export function showGlobalMessage() {
window.$message?.success('Global message')
}
Best Practices
-
Wrap with MessageProvider: Always use n-message-provider at app root
<n-message-provider>
<App />
</n-message-provider>
-
Use appropriate types: Match message type to context
success for positive outcomes
error for failures
warning for cautionary notes
info for neutral information
loading for async operations
-
Keep messages concise: Toast messages should be brief and clear
-
Use loading for async operations: Show loading state, then success/error
const msg = message.loading('Loading...', { duration: 0 })
msg.destroy()
message.success('Done')
-
Enable hover to keep for important messages: Allow users to read longer messages
message.info('Important info', { keepAliveOnHover: true })
-
Clean up messages: Use destroyAll when navigating between pages
-
Set reasonable duration: Default 3000ms works for most cases, adjust as needed