apps/docs/content/docs/cn/react/migration/(components)/popover.mdx
在 v2 中,Popover 由独立的多个组件组成:
import { Popover, PopoverTrigger, PopoverContent, Button } from "@heroui/react";
export default function App() {
return (
<Popover placement="right">
<PopoverTrigger>
<Button>Open</Button>
</PopoverTrigger>
<PopoverContent>
<div>Content</div>
</PopoverContent>
</Popover>
);
}
在 v3 中,Popover 改为复合组件:
import { Popover, Button } from "@heroui/react";
export default function App() {
return (
<Popover>
<Button>Open</Button>
<Popover.Content>
<Popover.Dialog>
<Popover.Heading>Title</Popover.Heading>
<div>Content</div>
</Popover.Dialog>
</Popover.Content>
</Popover>
);
}
v2: 独立的多个组件(Popover、PopoverTrigger、PopoverContent)
v3: 复合组件(Popover、Popover.Trigger、Popover.Content、Popover.Dialog、Popover.Heading、Popover.Arrow)
| v2 prop | v3 位置 | 说明 |
|---|---|---|
placement | placement(在 Content 上) | 移至 Popover.Content |
offset | offset(在 Content 上) | 移至 Popover.Content |
shouldFlip | shouldFlip(在 Content 上) | 移至 Popover.Content |
isOpen / defaultOpen / onOpenChange | 同名(在根上) | 受控状态仍保留在根 Popover 上 |
showArrow | — | 改用 Popover.Arrow 子组件 |
size | — | 已移除(请改用 Tailwind CSS) |
color | — | 已移除(请改用 Tailwind CSS) |
radius | — | 已移除(请改用 Tailwind CSS) |
shadow | — | 已移除(请改用 Tailwind CSS) |
backdrop | — | 已移除 |
motionProps | — | 已移除(动画机制已不同) |
classNames | — | 改在各子组件上使用 className |
onClose | — | 改用 onOpenChange((open) => { if (!open) { ... } }) |
<Tabs items={["v2", "v3"]}>
<Tab value="v2">
tsx <Popover showArrow> <PopoverTrigger><Button>Open</Button></PopoverTrigger> <PopoverContent><div>Content</div></PopoverContent> </Popover> <Popover placement="top"> <PopoverTrigger><Button>Open</Button></PopoverTrigger> <PopoverContent><div>Content</div></PopoverContent> </Popover> <Popover offset={10}> <PopoverTrigger><Button>Open</Button></PopoverTrigger> <PopoverContent><div>Content</div></PopoverContent> </Popover>
</Tab>
<Tab value="v3">
tsx <Popover> <Button>Open</Button> <Popover.Content> <Popover.Dialog> <Popover.Arrow /> <div>Content</div> </Popover.Dialog> </Popover.Content> </Popover> <Popover> <Button>Open</Button> <Popover.Content placement="top"> <Popover.Dialog> <Popover.Arrow /> <div>Content</div> </Popover.Dialog> </Popover.Content> </Popover> <Popover> <Button>Open</Button> <Popover.Content offset={10}> <Popover.Dialog> <div>Content</div> </Popover.Dialog> </Popover.Content> </Popover>
</Tab>
</Tabs>
<Tabs items={["v2", "v3"]}>
<Tab value="v2">
tsx <PopoverContent> <div className="px-1 py-2"> <div className="text-small font-bold">Title</div> <div className="text-tiny">Content</div> </div> </PopoverContent>
</Tab>
<Tab value="v3">
tsx <Popover.Content> <Popover.Dialog> <Popover.Heading>Title</Popover.Heading> <p className="text-muted mt-2 text-sm">Content</p> </Popover.Dialog> </Popover.Content>
</Tab>
</Tabs>
<Tabs items={["v2", "v3"]}> <Tab value="v2"> ```tsx import { useState } from "react";
const [isOpen, setIsOpen] = useState(false);
<Popover isOpen={isOpen} onOpenChange={setIsOpen}>
<PopoverTrigger>
<Button>Open</Button>
</PopoverTrigger>
<PopoverContent>
<div>Content</div>
</PopoverContent>
</Popover>
```
const [isOpen, setIsOpen] = useState(false);
<Popover isOpen={isOpen} onOpenChange={setIsOpen}>
<Button>Open</Button>
<Popover.Content>
<Popover.Dialog>
<div>Content</div>
</Popover.Dialog>
</Popover.Content>
</Popover>
```
<Tabs items={["v2", "v3"]}>
<Tab value="v2">
tsx <PopoverTrigger> <CustomButton>Custom</CustomButton> </PopoverTrigger>
</Tab>
<Tab value="v3">
tsx <Popover.Trigger> <CustomButton>Custom</CustomButton> </Popover.Trigger>
</Tab>
</Tabs>
v3 Popover 遵循以下结构:
Popover (Root)
├── Popover.Trigger (optional, or use Button directly)
└── Popover.Content
└── Popover.Dialog
├── Popover.Arrow (optional)
├── Popover.Heading (optional)
└── Content
在 v2 中,箭头通过根 Popover 上的 showArrow 布尔 prop 控制。在 v3 中,Popover.Arrow 是一个放置在 Popover.Content 内部的专用组件,让你可以完全控制其渲染:
<Popover>
<Button>Open</Button>
<Popover.Content>
<Popover.Arrow className="custom-arrow" />
<Popover.Dialog>
<div>Content</div>
</Popover.Dialog>
</Popover.Content>
</Popover>
Popover.Arrow 也接受 render prop,可完全自定义箭头的渲染。
受控的打开状态仍保留在根 Popover 组件上,prop 名称与 v2 一致:
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
isOpen | boolean | - | 控制 Popover 的可见性(受控) |
defaultOpen | boolean | false | 初始打开状态(非受控) |
onOpenChange | (isOpen: boolean) => void | - | 打开状态变化时触发 |
Popover.Content 与 Popover.Arrow 都支持 render prop,让你可以在高级场景下用自定义渲染函数覆盖默认 DOM 元素。
Popover.Content、Popover.Dialog 等)Popover.Trigger,或直接将 Button 作为子节点Popover.Dialog 中showArrow prop——改用 Popover.Arrow 子组件Popover.Heading 组件placement、offset、shouldFlip 移到 Popover.Content 上size、color、radius、shadow —— 请改用 Tailwind CSSbackdrop prop 已移除motionProps 已移除,动画机制已不同className prop