Popover
点击触发的轻量浮层容器,用于承载表单、操作和补充内容
Popover 用于在触发元素附近展示可交互浮层。组件基于 Radix Popover 封装,提供触发器、内容容器、Portal、箭头、关闭按钮、受控状态和定位能力。
import {
Popover,
PopoverAnchor,
PopoverArrow,
PopoverContent,
PopoverRoot,
PopoverTrigger
} from '@skyroc/web-ui';何时使用
- 需要点击按钮、图标或文本后展示一块可交互内容。
- 浮层里需要放置表单、筛选项、快捷设置或简短操作。
- 内容和触发元素关系明确,但不需要阻断页面流程。
- 只展示悬停信息时使用 HoverCard 或 Tooltip;需要强确认或复杂流程时使用 Dialog。
基础用法
通过 trigger 提供触发元素,children 作为浮层内容。默认内容会通过 Portal 渲染,并带有边框、阴影和进入/退出动画。
<Popover trigger={<Button>Open Popover</Button>}>
<div>Popover content</div>
</Popover>位置与箭头
通过 side 控制浮层位置,通过 showArrow 显示指向触发元素的箭头。side、align、sideOffset 等定位属性会传递给内容容器。
<Popover
showArrow
side="right"
sideOffset={8}
trigger={<Button>Open</Button>}
>
<div>Content</div>
</Popover>受控状态
通过 open 和 onOpenChange 控制打开状态;非受控模式使用 defaultOpen。
const [open, setOpen] = useState(false);
<Popover open={open} onOpenChange={setOpen} trigger={<Button>Open</Button>} />关闭按钮
通过 closeIcon 放置自定义关闭元素。该元素会通过 Radix Close asChild 绑定关闭行为。
<Popover
closeIcon={<Button variant="ghost">Close</Button>}
trigger={<Button>Open</Button>}
>
<div>Closable content</div>
</Popover>尺寸
通过 size 调整内容区 padding、字号和箭头尺寸,从 xs 到 2xl 共 6 个尺寸。
| 尺寸 | 内容间距 | 字号 | 适用场景 |
|---|---|---|---|
xs | p-3 | 10px | 紧凑说明、表格内嵌 |
sm | p-3.5 | 12px | 小型提示、工具设置 |
md | p-4 | 14px | 常规场景(默认) |
lg | p-4.5 | 16px | 操作表单、设置面板 |
xl | p-5 | 18px | 强调内容 |
2xl | p-5.5 | 20px | 大号浮层内容 |
API
Popover
通用属性参考:组合 Radix Popover Root、Portal 和 Content,并提供高层 trigger、closeIcon、showArrow 封装。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| trigger* | 触发 Popover 打开的元素,主组件用法中必须提供 | ReactNode | - |
| children | 浮层内容 | ReactNode | - |
| open | 受控模式下的打开状态 | boolean | - |
| defaultOpen | 非受控模式下的默认打开状态 | boolean | - |
| onOpenChange | 打开状态变化时触发 | (open: boolean) => void | - |
| modal | 是否使用模态交互模式 | boolean | - |
| side | 浮层相对触发元素的位置 | 'top' | 'right' | 'bottom' | 'left' | - |
| align | 浮层相对触发元素的对齐方式 | 'start' | 'center' | 'end' | - |
| sideOffset | 浮层和触发元素之间的距离 | number | 5 |
| alignOffset | 沿对齐轴偏移的距离 | number | - |
| avoidCollisions | 是否启用碰撞检测以避免浮层超出视口 | boolean | true |
| showArrow | 是否显示指向触发元素的箭头 | boolean | false |
| arrowWidth | 箭头宽度,透传给 PopoverArrow | number | - |
| arrowHeight | 箭头高度,透传给 PopoverArrow | number | - |
| arrowProps | 传递给 PopoverArrow 的额外 props,仅 showArrow 为 true 时生效 | PopoverArrowProps | - |
| closeIcon | 自定义关闭元素,会通过 Radix Close asChild 绑定关闭行为 | ReactNode | - |
| contentProps | 传递给 PopoverContent 的额外 props | PopoverContentProps | - |
| anchorProps | 传递给 PopoverAnchor 的额外 props | PopoverAnchorProps | - |
| container | Portal 挂载容器 | HTMLElement | - |
| disabledPortal | 是否禁用 Portal,直接在当前位置渲染内容 | boolean | false |
| forceMount | 强制挂载 Portal | true | - |
| forceMountPortal | 强制挂载 Portal 的别名字段 | true | - |
| size | 尺寸,影响内容区 padding、字号和箭头尺寸 | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'md' |
| className | 内容容器 class;优先级高于 classNames.content 和 contentProps.className | ClassValue | - |
| classNames | 各 slot 的自定义 class(anchor / content / arrow) | PopoverClassNames | - |
结构组件
Popover 同时导出 Radix 风格结构组件,适合需要完全手动组织 Root、Trigger、Content 和 Portal 时使用。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| PopoverRoot | Radix Popover Root 原语 | radix primitive | - |
| PopoverTrigger | Radix Popover Trigger 原语 | radix primitive | - |
| PopoverPortal | Radix Popover Portal 原语 | radix primitive | - |
| PopoverAnchor | 锚点元素,用于定位但不触发打开行为 | PopoverAnchorProps | - |
| PopoverContent | 浮层内容容器 | PopoverContentProps | - |
| PopoverArrow | 浮层箭头 | PopoverArrowProps | - |
类型
PopoverProps
主组件属性。组合 Radix Root、Portal、Content props,并增加 trigger、箭头和关闭元素等高层封装。
| 字段 | 类型 | 说明 |
|---|---|---|
| trigger* | ReactNode | 触发打开的元素。 |
| children | ReactNode | 浮层内容。 |
| open | boolean | 受控打开状态。 |
| defaultOpen | boolean | 默认打开状态。 |
| onOpenChange | (open: boolean) => void | 打开状态变化回调。 |
| modal | boolean | 是否使用模态交互模式。 |
| side | 'top' | 'right' | 'bottom' | 'left' | 浮层位置。 |
| align | 'start' | 'center' | 'end' | 浮层对齐方式。 |
| sideOffset | number | 浮层和触发元素之间的距离。 |
| alignOffset | number | 沿对齐轴偏移的距离。 |
| avoidCollisions | boolean | 是否启用碰撞检测。 |
| showArrow | boolean | 是否显示箭头。 |
| arrowWidth | number | 箭头宽度。 |
| arrowHeight | number | 箭头高度。 |
| arrowProps | PopoverArrowProps | 箭头组件属性。 |
| closeIcon | ReactNode | 关闭元素。 |
| contentProps | PopoverContentProps | 内容容器属性。 |
| anchorProps | PopoverAnchorProps | 锚点属性。 |
| container | HTMLElement | Portal 挂载容器。 |
| disabledPortal | boolean | 是否禁用 Portal。 |
| forceMount | true | 强制挂载 Portal。 |
| forceMountPortal | true | 强制挂载 Portal 的别名字段。 |
| size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 组件尺寸。 |
| className | ClassValue | 内容容器 class。 |
| classNames | PopoverClassNames | slot class 配置。 |
PopoverClassNames
Popover 各 slot 的自定义 class。
| 字段 | 类型 | 说明 |
|---|---|---|
| anchor | ClassValue | 锚点容器 class。 |
| content | ClassValue | 内容容器 class。 |
| arrow | ClassValue | 箭头 class。 |
PopoverContentProps
浮层内容容器属性,继承 Radix Popover Content props,并增加项目尺寸和 className 类型。
| 字段 | 类型 | 说明 |
|---|---|---|
| children | ReactNode | 内容节点。 |
| className | ClassValue | 内容容器 class。 |
| side | 'top' | 'right' | 'bottom' | 'left' | 浮层位置。 |
| align | 'start' | 'center' | 'end' | 浮层对齐方式。 |
| sideOffset | number | 浮层和触发元素之间的距离。默认 5。 |
| alignOffset | number | 沿对齐轴偏移的距离。 |
| avoidCollisions | boolean | 是否启用碰撞检测。默认 true。 |
| collisionPadding | number | side padding object | 碰撞检测时和边界之间保留的距离。 |
| onEscapeKeyDown | (event) => void | 按 Escape 时触发。 |
| onPointerDownOutside | (event) => void | 在浮层外按下指针时触发。 |
| onFocusOutside | (event) => void | 焦点移出浮层时触发。 |
| onInteractOutside | (event) => void | 浮层外发生交互时触发。 |
| size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 内容尺寸。 |
PopoverArrowProps
箭头属性,继承 Radix Popover Arrow props,并增加项目尺寸和 className 类型。
| 字段 | 类型 | 说明 |
|---|---|---|
| className | ClassValue | 箭头 class。 |
| width | number | 箭头宽度。 |
| height | number | 箭头高度。 |
| asChild | boolean | 使用子元素替代默认箭头元素。 |
| size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 箭头尺寸。 |
PopoverAnchorProps
锚点属性,继承 Radix Popover Anchor props,并增加项目尺寸和 className 类型。
| 字段 | 类型 | 说明 |
|---|---|---|
| children | ReactNode | 锚点内容。 |
| className | ClassValue | 锚点 class。 |
| asChild | boolean | 使用子元素作为锚点。 |
| size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 类型继承字段,当前锚点样式不直接使用。 |