Preview Updated 2026-05-10

Popover

An interactive variant of Tooltip — hosts arbitrary rich content, forms, and buttons; auto-flips near screen edges.

Basic usage

Unlike Tooltip, Popover supports any interactive content (inputs, buttons, lists). Click outside or press Esc to close; hovering into the popover does not close it.

背景
src/App.vue
<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>
import { CfButton, CfInput, CfPopover } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfPopover
      placement="bottom"
      content={
        <div>
          <strong>Quick actions</strong>
          <CfInput placeholder="Search…" size="sm" />
          <CfButton size="sm">Apply</CfButton>
        </div>
      }
      >
      <CfButton variant="secondary">Click to expand</CfButton>
      </CfPopover>
    </>
  );
}

Triggers

trigger controls how the popover opens:

  • click (default) — click the trigger to open, click again or click outside to close
  • hover — opens on hover, closes after a delay when the cursor leaves
  • manual — fully controlled by the parent via open
背景
src/App.vue
<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>
import { CfButton, CfPopover } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <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>
    </>
  );
}

Four placements

placementtop / bottom (default) / left / right. Auto-flips to the opposite side when there isn’t enough room.

背景
src/App.vue
<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>
import { CfPopover } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfPopover placement="top">…</CfPopover>
      <CfPopover placement="bottom">…</CfPopover>
      <CfPopover placement="left">…</CfPopover>
      <CfPopover placement="right">…</CfPopover>
    </>
  );
}

Fixed width

width gives the popover a fixed width (number or CSS string); omit to size to content. Useful for multi-column content or precise layout.

背景
src/App.vue
<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>
import { CfButton, CfPopover } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfPopover placement="bottom" content={...}><CfButton>Auto</CfButton></CfPopover>
      <CfPopover placement="bottom" width={320} content={...}><CfButton>Fixed 320</CfButton></CfPopover>
    </>
  );
}

API · Props

PropTypeDefaultDescription
openbooleanUsed in controlled mode together with update:open / onOpenChange
placement'top' | 'bottom' | 'left' | 'right''bottom'Preferred placement; auto-flips when there isn’t enough room
trigger'click' | 'hover' | 'manual''click'Trigger mode
offsetnumber8Gap to the trigger element (px)
closeOnOutsidebooleantrueClose on outside click (ignored when manual)
closeOnEscbooleantrueClose on Esc
widthnumber | stringFixed width; omit to size to content
disabledbooleanfalseDisable the trigger

API · Slots / children

NameDescription
default (children)Trigger element
contentPopover panel content (React uses the content prop)

反馈与讨论

Popover · Discussion

0
0 / 600
一键发送
正在加载评论...