Popover 是 ColorInput 打开选择器时使用的浮层。把它导出,是为了让你能把选择器放在自己的触发器后面,比如一个文字按钮或一个菜单项。如果 ColorInput 渲染的色块按钮不是你想要的控件,就用它。
它根据 anchor 定位:下方空间够就显示在下方,不够就显示在上方。它会渲染到 document.body 中。打开后,焦点移入弹出层,按 Tab 也不会跑出去。按 Escape 或点击外部会调用 onClose,按 Escape 还会把焦点还给锚点元素。打开状态由你管理,所以要在 onClose 里把它设回 false。在里面放一个 ChromaPanel,任何触发器都能打开 React 颜色选择器。
结构
import { useState } from "react";
import { ChromaPanel, Popover } from "chroma-panel";
export function BrandColorButton() {
const [anchor, setAnchor] = useState<HTMLButtonElement | null>(null);
const [open, setOpen] = useState(false);
return (
<>
<button
ref={setAnchor}
type="button"
aria-haspopup="dialog"
aria-expanded={open}
onClick={() => setOpen(!open)}
>
Brand color
</button>
<Popover anchor={anchor} open={open} onClose={() => setOpen(false)}>
<div role="dialog" aria-label="Brand color">
<ChromaPanel onClose={() => setOpen(false)} />
</div>
</Popover>
</>
);
}宽度小于 640px 时,它会变成底部面板。传入 sheetOnMobile={false},就能在任何宽度下都使用锚定的弹出层。
API 参考
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| anchor* | HTMLElement | null | — | The element to position against. Pass null while the trigger has not mounted. |
| open* | boolean | — | Whether the surface is shown. |
| onClose* | () => void | — | Fires on Escape, on an outside click, and on the sheet being dismissed. You own the open state, so this is where you close it. |
| offset | number | 8 | Gap in pixels between the anchor and the surface. |
| sheetOnMobile | boolean | true | Below 640px, render as a bottom sheet with a grab handle and a scrim. Turn off for an anchored popover at every width. |
| className | string | — | Class on the surface. |
| children* | React.ReactNode | — | What the surface contains. |
相关内容
- ColorInput:基于这个弹出层的现成触发器
- 浏览器支持:底部面板在手机上的表现
- 无障碍功能:整个选择器的焦点处理