使用场景
Popover 气泡卡片是由用户自主打开的临时性浮层卡片,能够承载一些额外内容和交互行为而不影响原页面。
和 Tooltip 的区别是,它可以承载更复杂的内容,而不仅仅是提示文本。
代码演示
如何引入
<script setup lang="ts">
import { Popover } from '@fibrous/semi-ui-vue';
</script>
注意事项
Popover 需要将触发属性和事件监听器应用到默认插槽的触发元素上,并以触发元素的真实 DOM 元素计算弹出层的定位,因此默认插槽支持如下类型:
- 单个真实 DOM 元素,如 span,div,p...
- 单个组件,需要让未声明的属性落到它的根 DOM 元素上(默认的 attrs 透传即可);根为多个节点的组件以它的第一个元素为锚点
- 文本或多个节点,Popover 会用一个 span 包裹它们作为触发元素
代码
<script setup lang="ts">
import { IllustrationSuccess, IllustrationSuccessDark } from '@fibrous/semi-illustrations-vue';
import { Empty, Popover, Space, Tag } from '@fibrous/semi-ui-vue';
const style = {
border: '2px solid var(--semi-color-border)',
paddingLeft: '4px',
paddingRight: '4px',
borderRadius: '4px',
};
const imageStyle = { width: '150px', height: '150px' };
</script>
<template>
<Space>
<Popover>
<Tag :style="style">Component</Tag>
<template #content>
<Empty :style="{ width: '400px', margin: '0 auto', display: 'flex', padding: '20px' }" title="先进的设计 / 研发协作方式">
<template #image>
<IllustrationSuccess :style="imageStyle" />
</template>
<template #darkModeImage>
<IllustrationSuccessDark :style="imageStyle" />
</template>
<template #description>使用 Semi D2C 快速还原 Figma 设计稿,一键转代码</template>
</Empty>
</template>
</Popover>
<Popover>
Text
<template #content>
<Empty :style="{ width: '400px', margin: '0 auto', display: 'flex', padding: '20px' }" title="先进的设计 / 研发协作方式">
<template #image>
<IllustrationSuccess :style="imageStyle" />
</template>
<template #darkModeImage>
<IllustrationSuccessDark :style="imageStyle" />
</template>
<template #description>使用 Semi D2C 快速还原 Figma 设计稿,一键转代码</template>
</Empty>
</template>
</Popover>
<Popover>
<span :style="style">DOM</span>
<template #content>
<Empty :style="{ width: '400px', margin: '0 auto', display: 'flex', padding: '20px' }" title="先进的设计 / 研发协作方式">
<template #image>
<IllustrationSuccess :style="imageStyle" />
</template>
<template #darkModeImage>
<IllustrationSuccessDark :style="imageStyle" />
</template>
<template #description>使用 Semi D2C 快速还原 Figma 设计稿,一键转代码</template>
</Empty>
</template>
</Popover>
</Space>
</template>基本使用
将浮层的触发器 Trigger 放在默认插槽中,使用 Popover 包裹(如下的例子中触发器为 Tag 元素)。浮层内容通过 #content 插槽传入
注意事项同 Tooltip
代码
<script setup lang="ts">
import { IllustrationSuccess, IllustrationSuccessDark } from '@fibrous/semi-illustrations-vue';
import { Empty, Popover, Tag } from '@fibrous/semi-ui-vue';
const imageStyle = { width: '150px', height: '150px' };
</script>
<template>
<Popover>
<Tag>悬停此处</Tag>
<template #content>
<Empty :style="{ width: '400px', margin: '0 auto', display: 'flex', padding: '20px' }" title="先进的设计 / 研发协作方式">
<template #image>
<IllustrationSuccess :style="imageStyle" />
</template>
<template #darkModeImage>
<IllustrationSuccessDark :style="imageStyle" />
</template>
<template #description>使用 Semi D2C 快速还原 Figma 设计稿,一键转代码</template>
</Empty>
</template>
</Popover>
</template>弹出位置
支持通过position设置浮层弹出方向,共支持十二个方向。
代码
<script setup lang="ts">
import { IllustrationSuccess, IllustrationSuccessDark } from '@fibrous/semi-illustrations-vue';
import { Empty, Popover, Tag, type Position } from '@fibrous/semi-ui-vue';
const tops: [Position, string][] = [
['topLeft', 'TL'],
['top', 'Top'],
['topRight', 'TR'],
];
const lefts: [Position, string][] = [
['leftTop', 'LT'],
['left', 'Left'],
['leftBottom', 'LB'],
];
const rights: [Position, string][] = [
['rightTop', 'RT'],
['right', 'Right'],
['rightBottom', 'RB'],
];
const bottoms: [Position, string][] = [
['bottomLeft', 'BL'],
['bottom', 'Bottom'],
['bottomRight', 'BR'],
];
const imageStyle = { width: '150px', height: '150px' };
</script>
<template>
<div>
<div :style="{ marginLeft: '80px', whiteSpace: 'nowrap' }">
<Popover v-for="[position, label] in tops" :key="position" :position="position">
<Tag :style="{ margin: '8px', padding: '20px' }">{{ label }}</Tag>
<template #content>
<Empty :style="{ width: '400px', margin: '0 auto', display: 'flex', padding: '20px' }" title="先进的设计 / 研发协作方式">
<template #image>
<IllustrationSuccess :style="imageStyle" />
</template>
<template #darkModeImage>
<IllustrationSuccessDark :style="imageStyle" />
</template>
<template #description>使用 Semi D2C 快速还原 Figma 设计稿,一键转代码</template>
</Empty>
</template>
</Popover>
</div>
<div :style="{ width: '80px', float: 'left' }">
<Popover v-for="[position, label] in lefts" :key="position" :position="position">
<Tag :style="{ margin: '8px', padding: '20px', width: '60px' }">{{ label }}</Tag>
<template #content>
<Empty :style="{ width: '400px', margin: '0 auto', display: 'flex', padding: '20px' }" title="先进的设计 / 研发协作方式">
<template #image>
<IllustrationSuccess :style="imageStyle" />
</template>
<template #darkModeImage>
<IllustrationSuccessDark :style="imageStyle" />
</template>
<template #description>使用 Semi D2C 快速还原 Figma 设计稿,一键转代码</template>
</Empty>
</template>
</Popover>
</div>
<div :style="{ width: '40px', marginLeft: '300px' }">
<Popover v-for="[position, label] in rights" :key="position" :position="position">
<Tag :style="{ margin: '8px', padding: '20px', width: '60px' }">{{ label }}</Tag>
<template #content>
<Empty :style="{ width: '400px', margin: '0 auto', display: 'flex', padding: '20px' }" title="先进的设计 / 研发协作方式">
<template #image>
<IllustrationSuccess :style="imageStyle" />
</template>
<template #darkModeImage>
<IllustrationSuccessDark :style="imageStyle" />
</template>
<template #description>使用 Semi D2C 快速还原 Figma 设计稿,一键转代码</template>
</Empty>
</template>
</Popover>
</div>
<div :style="{ marginLeft: '80px', clear: 'both', whiteSpace: 'nowrap' }">
<Popover v-for="[position, label] in bottoms" :key="position" :position="position">
<Tag :style="{ margin: '8px', padding: '20px', width: '60px' }">{{ label }}</Tag>
<template #content>
<Empty :style="{ width: '400px', margin: '0 auto', display: 'flex', padding: '20px' }" title="先进的设计 / 研发协作方式">
<template #image>
<IllustrationSuccess :style="imageStyle" />
</template>
<template #darkModeImage>
<IllustrationSuccessDark :style="imageStyle" />
</template>
<template #description>使用 Semi D2C 快速还原 Figma 设计稿,一键转代码</template>
</Empty>
</template>
</Popover>
</div>
</div>
</template>受控显示
设置 trigger="custom",此场景下,Popover 的显示与否完全受到参数 visible 的控制,可以配合 v-model:visible 使用。
代码
<script setup lang="ts">
import { ref } from 'vue';
import { IllustrationSuccess, IllustrationSuccessDark } from '@fibrous/semi-illustrations-vue';
import { Empty, Popover, Radio, RadioGroup, type RadioValue } from '@fibrous/semi-ui-vue';
const visible = ref<RadioValue | undefined>(0);
const imageStyle = { width: '150px', height: '150px' };
</script>
<template>
<Popover trigger="custom" :visible="visible === 1">
<span :style="{ display: 'inline-block' }">
<RadioGroup v-model="visible" type="button">
<Radio :value="1">受控显示</Radio>
<Radio :value="0">受控隐藏</Radio>
</RadioGroup>
</span>
<template #content>
<Empty :style="{ width: '400px', margin: '0 auto', display: 'flex', padding: '20px' }" title="先进的设计 / 研发协作方式">
<template #image>
<IllustrationSuccess :style="imageStyle" />
</template>
<template #darkModeImage>
<IllustrationSuccessDark :style="imageStyle" />
</template>
<template #description>使用 Semi D2C 快速还原 Figma 设计稿,一键转代码</template>
</Empty>
</template>
</Popover>
</template>condition 条件触发
当 :condition="false" 时,Popover 不响应 hover/click/focus 等触发行为(trigger="custom" 时仍按 visible 显示);condition 由 true 变为 false 时,已显示的弹出层立即关闭;visible 受控时只发出 update:visible 与 visibleChange(false),使用方回写 visible 后才关闭。
代码
<script setup lang="ts">
import { computed, ref } from 'vue';
import { Button, Popover, Space, Switch, Typography } from '@fibrous/semi-ui-vue';
const { Text } = Typography;
const enabled = ref(true);
const content = computed(() => `condition is ${enabled.value ? 'true' : 'false'}`);
</script>
<template>
<Space align="center">
<Text id="popover-condition-label">condition</Text>
<Switch v-model="enabled" aria-labelledby="popover-condition-label" />
<Popover :condition="enabled">
<Button>Hover me</Button>
<template #content>{{ content }}</template>
</Popover>
<Popover :condition="enabled" trigger="click">
<Button>Click me</Button>
<template #content>{{ content }}</template>
</Popover>
</Space>
</template>显示小三角
通过设置showArrow, Popover 同样也支持展示一个小三角。
这种模式下浮层会拥有一个默认的样式,你可以通过传递 style 参数来覆盖掉。
代码
<script setup lang="ts">
import { Popover, Tag, type Position } from '@fibrous/semi-ui-vue';
const tops: [Position, string][] = [
['topLeft', 'TL'],
['top', 'Top'],
['topRight', 'TR'],
];
const lefts: [Position, string][] = [
['leftTop', 'LT'],
['left', 'Left'],
['leftBottom', 'LB'],
];
const rights: [Position, string][] = [
['rightTop', 'RT'],
['right', 'Right'],
['rightBottom', 'RB'],
];
const bottoms: [Position, string][] = [
['bottomLeft', 'BL'],
['bottom', 'Bottom'],
['bottomRight', 'BR'],
];
</script>
<template>
<div class="tag-margin-right" :style="{ paddingLeft: '40px' }">
<div :style="{ marginLeft: '40px', whiteSpace: 'nowrap' }">
<Popover v-for="[position, label] in tops" :key="position" :position="position" showArrow>
<Tag>{{ label }}</Tag>
<template #content>
<article>
Hi ByteDancer, this is a popover.
<br />
We have 2 lines.
</article>
</template>
</Popover>
</div>
<div :style="{ width: '40px', float: 'left' }">
<Popover v-for="[position, label] in lefts" :key="position" :position="position" showArrow>
<Tag>{{ label }}</Tag>
<template #content>
<article>
Hi ByteDancer, this is a popover.
<br />
We have 2 lines.
</article>
</template>
</Popover>
</div>
<div :style="{ width: '40px', marginLeft: '180px' }">
<Popover v-for="[position, label] in rights" :key="position" :position="position" showArrow>
<Tag>{{ label }}</Tag>
<template #content>
<article>
Hi ByteDancer, this is a popover.
<br />
We have 2 lines.
</article>
</template>
</Popover>
</div>
<div :style="{ marginLeft: '40px', clear: 'both', whiteSpace: 'nowrap' }">
<Popover v-for="[position, label] in bottoms" :key="position" :position="position" showArrow>
<Tag>{{ label }}</Tag>
<template #content>
<article>
Hi ByteDancer, this is a popover.
<br />
We have 2 lines.
</article>
</template>
</Popover>
</div>
</div>
</template>指向元素中心
在显示小三角的条件(showArrow=true)下,可以传入 arrowPointAtCenter=true 使得小三角始终指向元素中心位置。
代码
<script setup lang="ts">
import { Popover, Tag, type Position } from '@fibrous/semi-ui-vue';
const tops: [Position, string][] = [
['topLeft', 'TL'],
['top', 'Top'],
['topRight', 'TR'],
];
const lefts: [Position, string][] = [
['leftTop', 'LT'],
['left', 'Left'],
['leftBottom', 'LB'],
];
const rights: [Position, string][] = [
['rightTop', 'RT'],
['right', 'Right'],
['rightBottom', 'RB'],
];
const bottoms: [Position, string][] = [
['bottomLeft', 'BL'],
['bottom', 'Bottom'],
['bottomRight', 'BR'],
];
</script>
<template>
<div class="tag-margin-right" :style="{ paddingLeft: '40px' }">
<div :style="{ marginLeft: '40px', whiteSpace: 'nowrap' }">
<Popover v-for="[position, label] in tops" :key="position" arrowPointAtCenter :position="position" showArrow>
<Tag>{{ label }}</Tag>
<template #content>
<article>
Hi ByteDancer, this is a popover.
<br />
We have 2 lines.
</article>
</template>
</Popover>
</div>
<div :style="{ width: '40px', float: 'left' }">
<Popover v-for="[position, label] in lefts" :key="position" arrowPointAtCenter :position="position" showArrow>
<Tag>{{ label }}</Tag>
<template #content>
<article>
Hi ByteDancer, this is a popover.
<br />
We have 2 lines.
</article>
</template>
</Popover>
</div>
<div :style="{ width: '40px', marginLeft: '180px' }">
<Popover v-for="[position, label] in rights" :key="position" arrowPointAtCenter :position="position" showArrow>
<Tag>{{ label }}</Tag>
<template #content>
<article>
Hi ByteDancer, this is a popover.
<br />
We have 2 lines.
</article>
</template>
</Popover>
</div>
<div :style="{ marginLeft: '40px', clear: 'both', whiteSpace: 'nowrap' }">
<Popover v-for="[position, label] in bottoms" :key="position" arrowPointAtCenter :position="position" showArrow>
<Tag>{{ label }}</Tag>
<template #content>
<article>
Hi ByteDancer, this is a popover.
<br />
We have 2 lines.
</article>
</template>
</Popover>
</div>
</div>
</template>设置浮层背景色
如果你需要定制浮层的背景色或边框颜色,请务必单独声明 style 中的 backgroundColor 和 borderColor 属性,这样能够使得“小三角”也能应用相同的背景色和边框颜色。
代码
<script setup lang="ts">
import { Popover, Tag } from '@fibrous/semi-ui-vue';
</script>
<template>
<div>
<Popover
aria-label="Colorful Popover"
position="right"
showArrow
:style="{
backgroundColor: 'var(--semi-blue-6)',
borderColor: 'var(--semi-blue-6)',
color: 'var(--semi-color-white)',
borderWidth: '1px',
borderStyle: 'solid',
}"
trigger="custom"
visible
>
<Tag :style="{ backgroundColor: 'var(--semi-blue-6)', color: 'var(--semi-color-white)' }"> Colorful Popover </Tag>
<template #content>
<article :style="{ padding: '4px' }">Hi, Semi UI Popover.</article>
</template>
</Popover>
</div>
</template>初始化弹出层焦点位置
#content 插槽的作用域参数为 { initialFocusRef },用 :ref 将它绑定在可聚焦 DOM 或组件上,打开面板时会自动聚焦在该位置。
代码
<script setup lang="ts">
import { Button, Input, Popover, Space } from '@fibrous/semi-ui-vue';
</script>
<template>
<Popover trigger="click">
<Button>click me</Button>
<template #content="{ initialFocusRef }">
<div :style="{ padding: '12px' }">
<Space>
<Button>first focusable element</Button>
<Input :ref="initialFocusRef" placeholder="focus here" />
</Space>
</div>
</template>
</Popover>
</template>搭配 Tooltip 或 Popconfirm 使用
请参考搭配使用
API 参考
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| ariaLabel | 弹出层 role 为 dialog 时的 aria-label。 | string | semiGlobalDefault("Popover", "ariaLabel") |
| ariaLabelledby | 弹出层 role 为 dialog 时的 aria-labelledby。 | string | semiGlobalDefault("Popover", "ariaLabelledby") |
| ariaDescribedby | 弹出层 role 为 dialog 时的 aria-describedby。 | string | semiGlobalDefault("Popover", "ariaDescribedby") |
| role | 弹出层的 role。不传时 trigger 为 click、contextMenu、custom 是 dialog,其余是 tooltip;弹出层只是另一个控件的附属(如 combobox 的下拉)时传 presentation。 | string | semiGlobalDefault("Popover", "role") |
| autoAdjustOverflow | 弹出层被遮挡时是否自动调整方向。 | boolean | semiDefault("Popover", "autoAdjustOverflow", true) |
| visible | 弹出层是否显示,配合 trigger 为 custom 与 v-model:visible 使用;传入后由该值决定显示。 | boolean | semiGlobalDefault("Popover", "visible") |
| position | 弹出层相对触发元素的位置,共十二个方向。 | Type"top" | "bottom" | "left" | "right" | "topLeft" | "topRight" | "leftTop" | "leftBottom" | "rightTop" | "rightBottom" | "bottomLeft" | "bottomRight" | "leftTopOver" | "rightTopOver" | "leftBottomOver" | "rightBottomOver" | semiDefault("Popover", "position", "bottom") |
| motion | 是否展示弹出层动画。 | boolean | semiDefault("Popover", "motion", true) |
| mouseEnterDelay | 指针移入后延迟显示的毫秒数,仅 trigger 为 hover 或 focus 时生效。 | number | semiGlobalDefault("Popover", "mouseEnterDelay") |
| mouseLeaveDelay | 指针移出后延迟隐藏的毫秒数,仅 trigger 为 hover 或 focus 时生效,不小于 mouseEnterDelay。 | number | semiGlobalDefault("Popover", "mouseLeaveDelay") |
| trigger | 触发显示的时机。custom 时显示与否完全由 visible 决定。 | "hover" | "focus" | "click" | "custom" | "contextMenu" | semiDefault("Popover", "trigger", "hover") |
| contentClassName | 弹出层内容卡片的类名。 | string | unknown[] | semiGlobalDefault("Popover", "contentClassName") |
| showArrow | 是否显示箭头三角形。 | boolean | semiDefault("Popover", "showArrow", false) |
| spacing | 弹出层与触发元素的距离,单位为像素;对象形式分别设置水平与垂直方向。不传时无箭头为 4,有箭头为 10。 | number | { x: number; y: number; } | semiGlobalDefault("Popover", "spacing") |
| stopPropagation | 是否阻止弹出层上的 click、mousedown 与焦点进出事件冒泡。 | string | boolean | semiGlobalDefault("Popover", "stopPropagation") |
| arrowStyle | 箭头的 borderColor、backgroundColor 与 borderOpacity;缺省跟随卡片 style 中的 backgroundColor 与 borderColor。 | ArrowStyle | semiGlobalDefault("Popover", "arrowStyle") |
| arrowPointAtCenter | 箭头是否指向触发元素中心,需要同时开启 showArrow。 | boolean | semiGlobalDefault("Popover", "arrowPointAtCenter") |
| prefixCls | 弹出层类名前缀,设置后弹出层不再带 Popover 的样式。 | string | semiDefault("Popover", "prefixCls", cssClasses.PREFIX) |
| closeOnEsc | 弹出层打开期间按 Esc 是否关闭弹出层;trigger 为 custom 时只触发 escKeyDown,由使用方决定是否关闭。 | boolean | semiDefault("Popover", "closeOnEsc", true) |
| guardFocus | 焦点位于弹出层内时,Tab 是否在弹出层内循环。 | boolean | semiDefault("Popover", "guardFocus", true) |
| returnFocusOnClose | 按 Esc 关闭弹出层后焦点是否回到触发元素。 | boolean | semiDefault("Popover", "returnFocusOnClose", true) |
| clickToHide | 点击弹出层及其内部任一元素时是否关闭弹出层。 | boolean | semiGlobalDefault("Popover", "clickToHide") |
| disableArrowKeyDown | 是否禁用在触发元素上按方向键把焦点移入弹出层。 | boolean | semiGlobalDefault("Popover", "disableArrowKeyDown") |
| disableFocusListener | trigger 为 hover 时,是否不响应键盘聚焦打开弹出层。 | boolean | semiGlobalDefault("Popover", "disableFocusListener") |
| keepDOM | 关闭时是否保留弹出层内容而不销毁。 | boolean | semiGlobalDefault("Popover", "keepDOM") |
| condition | 是否允许触发显示;仅显式设为 false 时,hover、click、focus 等触发行为不生效,trigger 为 custom 时仍按 visible 显示。由 true 变为 false 时立即关闭已显示的弹出层;visible 受控时只发出 update:visible 与 visibleChange(false),使用方回写后才关闭。 | boolean | semiGlobalDefault("Popover", "condition") |
Events
| 事件 | 说明 | 回调参数 |
|---|---|---|
| open | 弹出层显示、进场动画开始时触发,每次打开一次,早于 afterOpen,受控与非受控相同;悬停打开后指针已离开而撤回的打开不触发。 | [] |
| update:visible | 弹出层需要显示或隐藏时触发,供 v-model:visible 回写。 | [visible: boolean] |
| visibleChange | 弹出层显示状态变化时触发;visible 受控时只报告用户交互发起的请求,父组件自己改变 visible 不触发。 | [visible: boolean] |
| clickOutSide | 弹出层打开时在触发元素与弹出层以外的区域按下鼠标时触发,仅 trigger 为 click、contextMenu、custom 时有效。 | [event: MouseEvent] |
| escKeyDown | closeOnEsc 为 true 时,弹出层打开期间按 Esc 触发。 | [event: KeyboardEvent] |
| afterOpen | 弹出层打开且进场动画结束后触发;没有进场动画时打开后即触发,受控与非受控相同;进场结束前被关闭的打开不触发。 | [] |
| afterClose | 弹出层关闭且离场动画结束后触发。 | [] |
Slots
| 插槽 | 说明 | 作用域参数 |
|---|---|---|
| default | 触发元素。单个元素或组件直接接收触发属性,文本或多个节点会被 span 包裹。 | any |
| content | 卡片内容,作用域参数 initialFocusRef 绑定到弹出层打开时需要聚焦的元素。 | TypeRenderContentProps<FocusTarget> |
Exposes
| 名称 | 说明 | 类型 |
|---|---|---|
| focusTrigger | 让触发元素获得焦点,仅在 returnFocusOnClose 为 true 且 trigger 不是 custom 时生效。 | Type() => void |
| rePosition | 按触发器当前位置立即重新计算弹出层位置。弹出层已随滚动、窗口尺寸变化、触发器移动以及触发器或弹出层的尺寸变化自动重新定位,一般无需调用;跟随触发器移动会晚一帧,需要同一帧内对齐时调用。 | Type() => void |
class、style 落在弹出层上,其他未声明的属性会被丢弃;触发属性只加在触发元素上。所在子树被 <KeepAlive> 缓存(失活)时,弹出层按关闭处理并通知 update:visible、visibleChange(false);单向绑定 visible 为 true 的弹出层随缓存的子树隐藏,重新激活后再次显示。
Accessibility
ARIA
- 关于 role
- 当 Popover 的 trigger 为 click、contextMenu、custom 时,Popover 的 content 具有
dialogrole - 当 trigger 为 hover、focus 时,Popover 的 content 具有
tooltiprole role属性可覆盖默认值。dialog需要名称:传入aria-label,或用aria-labelledby指向 content 中的标题;未命名的 dialog 在开发环境会输出警告
- 当 Popover 的 trigger 为 click、contextMenu、custom 时,Popover 的 content 具有
- Popover 的 content
- content 的 wrapper 会被自动添加
id属性
- content 的 wrapper 会被自动添加
- Popover 的 children(
tooltip只会被添加aria-describedby;presentation等其他 role 不添加任何属性)- 会被自动添加 aria-expanded 属性,当 Popover 可见时,属性值为
true,不可见时为false - 会被自动添加 aria-haspopup 属性,为
dialog - 会被自动添加 aria-controls 属性,为 content 的 wrapper 的 id
- 会被自动添加 aria-expanded 属性,当 Popover 可见时,属性值为
键盘和焦点
- Popover 触发方式设置为 hover 时:鼠标悬浮或聚焦时打开 Popover
- Popover 触发方式设置为 click 时:点击触发器或聚焦时并使用 Enter 键打开 Popover
- Popover 激活后,按下方向键 ⬇️ 将焦点移动到 Popover 上,此时焦点默认处于 Popover 中第一个可交互元素上,用户也可自定义焦点位置(若 Popover 内无可交互元素则表现为无响应)
- 焦点处于 Popover 内时使用 Tab 键,焦点会在 Popover 内循环,使用 Shift + Tab 会反方向移动焦点
- 键盘用户能够通过按 Esc 关闭 Popover,关闭后焦点返回到触发器上(仅当 trigger 为 click 时)
设计变量
| Sass 变量 | 值 | 用法 |
|---|---|---|
| $animation_duration-popover-out | 100ms | popover-显示及收起动画-动画持续时间 |
| $animation_function-popover-out | cubic-bezier(0.215, 0.61, 0.355, 1) | popover-显示及收起动画-动画插值函数 |
| $horizontal-rate-popover | 0.24 | 水平方向矫正因子 |
| $color-popover_arrow-icon-default | unset | 箭头图标 |
| $color-popover-bg-default | var(--semi-color-bg-3) | 默认背景色 |
| $color-popover-border-default | var(--semi-color-border) | 默认描边颜色 |
| $color-popover-arrow-border | var(--semi-color-border) | 箭头描边颜色 |
| $color-popover-arrow-bg | var(--semi-color-bg-3) | 箭头默认背景色 |
| $width-popover_arrow | 24px | 水平箭头宽度 |
| $height-popover_arrow | 8px | 水平箭头高度 |
| $height-popover_arrow_vertical | 24px | 垂直箭头高度 |
| $width-popover_arrow_vertical | 8px | 垂直箭头宽度 |
| $width-popover_title-border | 1px | |
| $spacing-popover_title-padding | 8px | 气泡卡片标题内边距 |
| $spacing-popover_withArrow-padding | 12px | 带箭头的气泡卡片标题内边距 |
| $spacing-popover_arrow_adjusted_offset-y | 6px | 垂直方向上的校正偏移量,主要修正三角形有棱角的问题 |
| $spacing-popover_arrow_adjusted_offset-x | math.round($horizontal-rate-popover * $width-popover_arrow) | 水平方向上的校正偏移量,主要修正三角形有棱角的问题 |
| $radius-popover | var(--semi-border-radius-medium) | 气泡卡片的圆角大小 |
| $filter-popover-bg | none |
FAQ
-
为什么 Popover 浮层卡片的位置和浮层的触发器的相对位置不符合预期?
Popover 底层依赖了 Tooltip,Tooltip 为了计算定位,需要获取到 children 的真实 DOM 元素,因此 Popover 类型目前支持如下类型的 children:- 单个真实 DOM 元素,如 span,div,p...
- 单个组件,未声明的属性需要落到它的根 DOM 元素上;根为多个节点的组件以它的第一个元素为锚点
- 文本或多个节点,由 Popover 用一个 span 包裹
若触发元素的真实 DOM 节点宽高并非是你的触发内容的全部,则位置可能有出入。例如设置了 prefix、suffix 的 Input,Popover位置仍是相对于不包含前缀部分的 input 框进行定位,此时只要在 Input 外层再套一个 div 就能解决问题。
-
为什么 Popover 浮层卡片在靠近屏幕边界宽度不够时,丢失宽度意外换行?
在 chromium 104 后 对于屏幕边界文本宽度不够时的换行渲染策略发生变化,详细原因可查看 issue #1022,semi侧已经在v2.17.0版本修复了这个问题。