Element Plus Popover Component
Display rich content in a popup, triggered by hover, click, focus, or contextmenu.
When to Invoke
Invoke this skill when:
- User needs to show rich content in a popup
- User wants to create nested operations
- User needs to display tables or forms in a popup
- User wants to trigger popup by click or hover
- User asks about virtual triggering
Features
- 9 Placements: Same as Tooltip
- Multiple Triggers: hover, click, focus, contextmenu
- Rich Content: Support for complex content like tables, forms
- Virtual Triggering: Separate trigger and content elements
- Nested Components: Can nest other components
- Customizable Width: Configurable width
API Reference
Attributes
| Name | Description | Type | Default |
|---|---|---|---|
| trigger | How popover is triggered | 'click' | 'focus' | 'hover' | 'contextmenu' | Array |
hover |
| trigger-keys | Keyboard codes to control display | Array |
['Enter', 'Space'] |
| title | Popover title | string |
— |
| effect | Tooltip theme | 'dark' | 'light' |
light |
| content | Popover content | string |
'' |
| width | Popover width | string | number |
150 |
| placement | Popover placement | 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end' |
bottom |
| disabled | Whether Popover is disabled | boolean |
false |
| visible / v-model:visible | Whether popover is visible | boolean | null |
null |
| offset | Popover offset | number |
undefined |
| transition | Transition animation | string |
— |
| show-arrow | Whether arrow is displayed | boolean |
true |
| popper-options | popper.js parameters | object |
{} |
| popper-class | Custom class for popover | string |
— |
| popper-style | Custom style for popover | string | object |
— |
| show-after | Delay of appearance (ms) | number |
0 |
| hide-after | Delay of disappear (ms) | number |
200 |
| auto-close | Timeout to hide (ms) | number |
0 |
| tabindex | tabindex of Popover | number | string |
0 |
| teleported | Whether popover is teleported | boolean |
true |
| append-to | Which element popover appends to | CSSSelector | HTMLElement |
body |
| persistent | Whether popover persists when inactive | boolean |
true |
| virtual-triggering | Whether virtual triggering is enabled | boolean |
— |
| virtual-ref | Reference element for virtual triggering | HTMLElement |
— |
Slots
| Name | Description | Type |
|---|---|---|
| default | Content of popover | {hide: () => void} |
| reference | HTML element that triggers popover | — |
Events
| Name | Description | Type |
|---|---|---|
| show | Triggers when popover shows | () => void |
| before-enter | Triggers before entering transition | () => void |
| after-enter | Triggers after entering transition | () => void |
| hide | Triggers when popover hides | () => void |
| before-leave | Triggers before leaving transition | () => void |
| after-leave | Triggers after leaving transition | () => void |
Exposes
| Name | Description | Type |
|---|---|---|
| hide | Hide popover | () => void |
Usage Examples
Basic Usage
<template>
<el-popover
title="Title"
content="This is popover content"
trigger="click"
>
<template #reference>
<el-button>Click to activate</el-button>
</template>
</el-popover>
</template>
Hover Trigger
<template>
<el-popover
placement="top"
title="Title"
:width="200"
trigger="hover"
content="This is popover content"
>
<template #reference>
<el-button>Hover to activate</el-button>
</template>
</el-popover>
</template>
Rich Content
<template>
<el-popover placement="right" :width="400">
<template #reference>
<el-button>Click to see table</el-button>
</template>
<el-table :data="tableData">
<el-table-column prop="name" label="Name" />
<el-table-column prop="address" label="Address" />
</el-table>
</el-popover>
</template>
<script setup>
const tableData = [
{ name: 'Tom', address: 'No. 189, Grove St' },
{ name: 'Jack', address: 'No. 189, Grove St' }
]
</script>
Nested Operations
<template>
<el-popover placement="top" :width="160">
<template #reference>
<el-button>Delete</el-button>
</template>
<p>Are you sure to delete this?</p>
<div style="text-align: right; margin: 0">
<el-button size="small" text @click="visible = false">Cancel</el-button>
<el-button size="small" type="primary" @click="visible = false">
Confirm
</el-button>
</div>
</el-popover>
</template>
<script setup>
import { ref } from 'vue'
const visible = ref(false)
</script>
With Form
<template>
<el-popover placement="bottom" :width="300" trigger="click">
<template #reference>
<el-button>Open Form</el-button>
</template>
<el-form :model="form" label-width="80px">
<el-form-item label="Name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="Email">
<el-input v-model="form.email" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm">Submit</el-button>
</el-form-item>
</el-form>
</el-popover>
</template>
<script setup>
import { reactive } from 'vue'
const form = reactive({
name: '',
email: ''
})
const submitForm = () => {
console.log('Form submitted:', form)
}
</script>
Virtual Triggering
<template>
<el-button ref="buttonRef">Trigger</el-button>
<el-popover
virtual-triggering
:virtual-ref="buttonRef"
content="Virtual popover content"
/>
</template>
<script setup>
import { ref } from 'vue'
const buttonRef = ref()
</script>
Controlled Visibility
<template>
<el-popover v-model:visible="visible" content="Controlled popover">
<template #reference>
<el-button @click="visible = !visible">Toggle</el-button>
</template>
</el-popover>
</template>
<script setup>
import { ref } from 'vue'
const visible = ref(false)
</script>
Multiple Triggers
<template>
<el-popover
:trigger="['click', 'hover']"
content="Multiple triggers"
>
<template #reference>
<el-button>Click or Hover</el-button>
</template>
</el-popover>
</template>
Custom Width
<template>
<el-popover :width="300" content="Wide popover content">
<template #reference>
<el-button>Wide Popover</el-button>
</template>
</el-popover>
</template>
No Arrow
<template>
<el-popover :show-arrow="false" content="No arrow popover">
<template #reference>
<el-button>No Arrow</el-button>
</template>
</el-popover>
</template>
Close from Content
<template>
<el-popover placement="top" :width="200">
<template #reference>
<el-button>Click</el-button>
</template>
<template #default="{ hide }">
<p>Click button to close</p>
<el-button @click="hide">Close</el-button>
</template>
</el-popover>
</template>
Common Issues
1. Popover Not Closing
Use hide function from slot:
<el-popover>
<template #default="{ hide }">
<el-button @click="hide">Close</el-button>
</template>
</el-popover>
2. Popover Position Issues
Use placement and fallback-placements:
<el-popover
placement="top"
:fallback-placements="['bottom', 'left', 'right']"
>
</el-popover>
3. Click Outside Not Closing
Set trigger="click":
<el-popover trigger="click">
</el-popover>
Best Practices
- Use appropriate trigger: Choose trigger based on use case
- Set width: Set appropriate width for content
- Close from content: Use
hidefunction for custom close - Virtual triggering: Use for complex trigger scenarios
- Controlled visibility: Use v-model:visible for programmatic control