Popover 弹出层
Tooltip 的可交互变体 —— 支持任意富内容、表单、按钮,自动避让屏幕边缘。
基础用法
与 Tooltip 不同,Popover 内部支持任意可交互内容(输入、按钮、列表)。点击外部或按 Esc 关闭,鼠标移入悬停 Popover 不会关闭。
背景
<script setup lang="ts">
import { CfButton, CfPopover, CfInput } from '@chufix-design/vue';
</script>
<template>
<CfPopover placement="bottom">
<CfButton variant="secondary">点击展开</CfButton>
<template #content>
<div style="display: flex; flex-direction: column; gap: 8px; min-width: 200px;">
<strong>快速操作</strong>
<CfInput placeholder="搜索…" size="sm" />
<CfButton size="sm">应用</CfButton>
</div>
</template>
</CfPopover>
</template> <script setup>
import { CfButton, CfPopover, CfInput } from '@chufix-design/vue';
</script>
<template>
<CfPopover placement="bottom">
<CfButton variant="secondary">点击展开</CfButton>
<template #content>
<div style="display: flex; flex-direction: column; gap: 8px; min-width: 200px;">
<strong>快速操作</strong>
<CfInput placeholder="搜索…" size="sm" />
<CfButton size="sm">应用</CfButton>
</div>
</template>
</CfPopover>
</template> <CfPopover
placement="bottom"
content={
<div>
<strong>快速操作</strong>
<CfInput placeholder="搜索…" size="sm" />
<CfButton size="sm">应用</CfButton>
</div>
}
>
<CfButton variant="secondary">点击展开</CfButton>
</CfPopover> <CfPopover
placement="bottom"
content={
<div>
<strong>快速操作</strong>
<CfInput placeholder="搜索…" size="sm" />
<CfButton size="sm">应用</CfButton>
</div>
}
>
<CfButton variant="secondary">点击展开</CfButton>
</CfPopover> 触发方式
trigger 决定如何打开 popover:
click(默认)—— 点击触发器打开,再点击或点外部关闭hover—— 悬停打开,移开延时关闭manual—— 完全由父组件通过open控制(受控模式)
背景
<script setup lang="ts">
import { ref } from 'vue';
import { CfButton, CfPopover } from '@chufix-design/vue';
const manualOpen = ref(false);
</script>
<template>
<div style="display: flex; gap: 12px; align-items: center; flex-wrap: wrap;">
<CfPopover trigger="click" placement="bottom">
<CfButton variant="secondary">click</CfButton>
<template #content>点击触发,再次点击或点外部关闭</template>
</CfPopover>
<CfPopover trigger="hover" placement="bottom">
<CfButton variant="secondary">hover</CfButton>
<template #content>悬停触发,鼠标移开延时关闭</template>
</CfPopover>
<CfPopover trigger="manual" :open="manualOpen" @update:open="(v) => manualOpen = v">
<CfButton variant="secondary" @click="manualOpen = !manualOpen">
manual ({{ manualOpen ? '已开' : '已关' }})
</CfButton>
<template #content>受控模式 — 完全由父组件 open 决定</template>
</CfPopover>
</div>
</template> <script setup>
import { ref } from 'vue';
import { CfButton, CfPopover } from '@chufix-design/vue';
const manualOpen = ref(false);
</script>
<template>
<div style="display: flex; gap: 12px; align-items: center; flex-wrap: wrap;">
<CfPopover trigger="click" placement="bottom">
<CfButton variant="secondary">click</CfButton>
<template #content>点击触发,再次点击或点外部关闭</template>
</CfPopover>
<CfPopover trigger="hover" placement="bottom">
<CfButton variant="secondary">hover</CfButton>
<template #content>悬停触发,鼠标移开延时关闭</template>
</CfPopover>
<CfPopover trigger="manual" :open="manualOpen" @update:open="(v) => manualOpen = v">
<CfButton variant="secondary" @click="manualOpen = !manualOpen">
manual ({{ manualOpen ? '已开' : '已关' }})
</CfButton>
<template #content>受控模式 — 完全由父组件 open 决定</template>
</CfPopover>
</div>
</template> <CfPopover trigger="click" content={...}><CfButton>click</CfButton></CfPopover>
<CfPopover trigger="hover" content={...}><CfButton>hover</CfButton></CfPopover>
<CfPopover trigger="manual" open={open} onOpenChange={setOpen} content={...}>
<CfButton onClick={() => setOpen(!open)}>manual</CfButton>
</CfPopover> <CfPopover trigger="click" content={...}><CfButton>click</CfButton></CfPopover>
<CfPopover trigger="hover" content={...}><CfButton>hover</CfButton></CfPopover>
<CfPopover trigger="manual" open={open} onOpenChange={setOpen} content={...}>
<CfButton onClick={() => setOpen(!open)}>manual</CfButton>
</CfPopover> 4 种 placement
placement —— top / bottom(默认)/ left / right,空间不够时自动翻转到对侧。
背景
<script setup lang="ts">
import { CfButton, CfPopover } from '@chufix-design/vue';
</script>
<template>
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; max-width: 320px;">
<CfPopover placement="top">
<CfButton variant="secondary">top</CfButton>
<template #content>位于触发器上方</template>
</CfPopover>
<CfPopover placement="bottom">
<CfButton variant="secondary">bottom</CfButton>
<template #content>位于触发器下方</template>
</CfPopover>
<CfPopover placement="left">
<CfButton variant="secondary">left</CfButton>
<template #content>位于触发器左侧</template>
</CfPopover>
<CfPopover placement="right">
<CfButton variant="secondary">right</CfButton>
<template #content>位于触发器右侧</template>
</CfPopover>
</div>
</template> <script setup>
import { CfButton, CfPopover } from '@chufix-design/vue';
</script>
<template>
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; max-width: 320px;">
<CfPopover placement="top">
<CfButton variant="secondary">top</CfButton>
<template #content>位于触发器上方</template>
</CfPopover>
<CfPopover placement="bottom">
<CfButton variant="secondary">bottom</CfButton>
<template #content>位于触发器下方</template>
</CfPopover>
<CfPopover placement="left">
<CfButton variant="secondary">left</CfButton>
<template #content>位于触发器左侧</template>
</CfPopover>
<CfPopover placement="right">
<CfButton variant="secondary">right</CfButton>
<template #content>位于触发器右侧</template>
</CfPopover>
</div>
</template> <CfPopover placement="top">…</CfPopover>
<CfPopover placement="bottom">…</CfPopover>
<CfPopover placement="left">…</CfPopover>
<CfPopover placement="right">…</CfPopover> <CfPopover placement="top">…</CfPopover>
<CfPopover placement="bottom">…</CfPopover>
<CfPopover placement="left">…</CfPopover>
<CfPopover placement="right">…</CfPopover> 固定宽度
width 给 popover 一个固定宽度(数字或 CSS 字符串);省略则按内容自适应。需要多列内容或精准排版时用。
背景
<script setup lang="ts">
import { CfButton, CfPopover } from '@chufix-design/vue';
</script>
<template>
<div style="display: flex; gap: 12px;">
<CfPopover placement="bottom">
<CfButton variant="secondary">自适应宽度</CfButton>
<template #content>仅按内容自然撑开</template>
</CfPopover>
<CfPopover placement="bottom" :width="320">
<CfButton variant="secondary">固定宽度 320</CfButton>
<template #content>
<p style="margin: 0;">这条 popover 强制 320px 宽,便于复杂布局。</p>
</template>
</CfPopover>
</div>
</template> <script setup>
import { CfButton, CfPopover } from '@chufix-design/vue';
</script>
<template>
<div style="display: flex; gap: 12px;">
<CfPopover placement="bottom">
<CfButton variant="secondary">自适应宽度</CfButton>
<template #content>仅按内容自然撑开</template>
</CfPopover>
<CfPopover placement="bottom" :width="320">
<CfButton variant="secondary">固定宽度 320</CfButton>
<template #content>
<p style="margin: 0;">这条 popover 强制 320px 宽,便于复杂布局。</p>
</template>
</CfPopover>
</div>
</template> <CfPopover placement="bottom" content={...}><CfButton>自适应</CfButton></CfPopover>
<CfPopover placement="bottom" width={320} content={...}><CfButton>固定 320</CfButton></CfPopover> <CfPopover placement="bottom" content={...}><CfButton>自适应</CfButton></CfPopover>
<CfPopover placement="bottom" width={320} content={...}><CfButton>固定 320</CfButton></CfPopover> API · Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
open | boolean | — | 受控时使用,配合 update:open / onOpenChange |
placement | 'top' | 'bottom' | 'left' | 'right' | 'bottom' | 首选位置;空间不够时自动翻转到对侧 |
trigger | 'click' | 'hover' | 'manual' | 'click' | 触发方式 |
offset | number | 8 | 与触发元素的间距(px) |
closeOnOutside | boolean | true | 点击外部时关闭(manual 时忽略) |
closeOnEsc | boolean | true | Esc 关闭 |
width | number | string | — | 固定宽度,省略则自适应内容 |
disabled | boolean | false | 禁用触发 |
API · Slots / 子节点
| 名称 | 说明 |
|---|---|
default (children) | 触发元素 |
content | Popover 面板内容(React 用 content prop) |
反馈与讨论
Popover 弹出层 的讨论