Popover 气泡卡片Popover
点击一个按钮,在它旁边弹出一小块可以交互的内容:筛选条件、快速编辑、补充设置。它不打断页面(非模态)。只是一句说明用 Tooltip;一串操作用 Menu;需要用户必须处理完才能继续时用 Dialog。
基本用法
trigger 是一个能接收 ref 和事件的元素,通常是 Button。打开时焦点移进浮层,Esc 或点外面关闭,关闭后焦点回到触发按钮。记得给浮层 aria-label。
位置
placement 由“方向”和可选的“对齐”组成,默认 bottom(居中)。放不下时自动翻到对面,并沿边缘平移回视口内。
受控与关闭
children 传函数可以拿到 close(关闭并把焦点还给触发按钮)。用 open / onOpenChange 受控。想指定打开时聚焦谁,给那个元素加 data-autofocus,或传 initialFocus。
当前名称:未命名项目 · 浮层已关闭
关闭方式
closeOnOutsidePress / closeOnEscape 可以分别关掉。两个都关时,浮层里必须有一个明确的关闭按钮。
相对别的元素定位
anchorRef 让浮层相对另一个元素定位(触发按钮仍然负责开关)。matchWidth 让浮层和锚点等宽,'min' 表示不窄于锚点。
浮层相对这一整条定位
API
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
trigger* | ReactElement | — | 触发元素:要能接收 ref 和事件。会被补上 aria-haspopup、aria-expanded、aria-controls 和 onClick。 |
children* | ReactNode | ({ close }) => ReactNode | — | 内容;传函数可以拿到 close。 |
open | boolean | — | 是否打开(受控)。 |
defaultOpen | boolean | false | 初始是否打开(非受控)。 |
onOpenChange | (open: boolean) => void | — | 开关状态变化时触发。 |
placement | 'top' | 'bottom' | 'left' | 'right' 及其 -start / -end | 'bottom' | 相对锚点的位置。 |
offset | number | 8 | 与锚点的间距(px)。 |
matchWidth | boolean | 'min' | false | true:与锚点等宽;'min':不窄于锚点。 |
anchorRef | RefObject<Element> | — | 相对另一个元素定位,默认相对触发元素。 |
initialFocus | RefObject<HTMLElement> | — | 打开时聚焦的元素;不传则找 [data-autofocus],再是第一个可聚焦元素,最后是浮层本身。 |
autoFocus | boolean | true | 打开时是否把焦点移进去。 |
closeOnOutsidePress | boolean | true | 点外面关闭。 |
closeOnEscape | boolean | true | 按 Esc 关闭。 |
role | string | 'dialog' | 浮层的角色。 |
…rest | HTMLAttributes<HTMLDivElement> | — | 其余属性(aria-label、className…)和 ref 落在浮层上。 |
无障碍
- 浮层是
role="dialog"(非模态),请用aria-label或aria-labelledby给它起名。触发元素带aria-haspopup="dialog"和aria-expanded。 - Enter / Space 在触发按钮上打开或关闭;打开后焦点移进浮层。
- Esc 关闭并把焦点还给触发按钮;点外面关闭时不抢焦点。
- 不困住焦点:Tab 走过最后一个元素(或 Shift+Tab 走过第一个)时浮层关闭,焦点从触发按钮继续往下(上)走。
- 浮层渲染在 body 末尾的 portal 里;嵌套的浮层(浮层里的 Select 等)点击时不算“点外面”。
- 不要用悬停触发 Popover——触屏和键盘用户用不了。