ProComponents, templates & AI tooling
HeroUI
27.7k

Popover

Popover 从 HeroUI v2 到 v3 的迁移指南。

完整的 API 参考、样式指南与高级示例请参阅 v3 Popover 文档。本指南只关注从 HeroUI v2 的迁移。

结构变化

在 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>
  );
}

主要变化

1. 组件结构

v2: 独立的多个组件(PopoverPopoverTriggerPopoverContent
v3: 复合组件(PopoverPopover.TriggerPopover.ContentPopover.DialogPopover.HeadingPopover.Arrow

2. Prop 变更

v2 propv3 位置说明
placementplacement(在 Content 上)移至 Popover.Content
offsetoffset(在 Content 上)移至 Popover.Content
shouldFlipshouldFlip(在 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) { ... } })

迁移示例

内容配置

{/* With arrow */}
<Popover showArrow>
  <PopoverTrigger><Button>Open</Button></PopoverTrigger>
  <PopoverContent><div>Content</div></PopoverContent>
</Popover>

{/* With placement */}
<Popover placement="top">
  <PopoverTrigger><Button>Open</Button></PopoverTrigger>
  <PopoverContent><div>Content</div></PopoverContent>
</Popover>

{/* With offset */}
<Popover offset={10}>
  <PopoverTrigger><Button>Open</Button></PopoverTrigger>
  <PopoverContent><div>Content</div></PopoverContent>
</Popover>
{/* With arrow - use component */}
<Popover>
  <Button>Open</Button>
  <Popover.Content>
    <Popover.Dialog>
      <Popover.Arrow />
      <div>Content</div>
    </Popover.Dialog>
  </Popover.Content>
</Popover>

{/* With placement - moved to Content */}
<Popover>
  <Button>Open</Button>
  <Popover.Content placement="top">
    <Popover.Dialog>
      <Popover.Arrow />
      <div>Content</div>
    </Popover.Dialog>
  </Popover.Content>
</Popover>

{/* With offset - moved to Content */}
<Popover>
  <Button>Open</Button>
  <Popover.Content offset={10}>
    <Popover.Dialog>
      <div>Content</div>
    </Popover.Dialog>
  </Popover.Content>
</Popover>

带标题

<PopoverContent>
  <div className="px-1 py-2">
    <div className="text-small font-bold">Title</div>
    <div className="text-tiny">Content</div>
  </div>
</PopoverContent>
<Popover.Content>
  <Popover.Dialog>
    <Popover.Heading>Title</Popover.Heading>
    <p className="text-muted mt-2 text-sm">Content</p>
  </Popover.Dialog>
</Popover.Content>

受控

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>
import { useState } from "react";

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>

自定义触发器

<PopoverTrigger>
  <CustomButton>Custom</CustomButton>
</PopoverTrigger>
<Popover.Trigger>
  <CustomButton>Custom</CustomButton>
</Popover.Trigger>

组件结构

v3 Popover 遵循以下结构:

Popover (Root)
  ├── Popover.Trigger (optional, or use Button directly)
  └── Popover.Content
      └── Popover.Dialog
          ├── Popover.Arrow (optional)
          ├── Popover.Heading (optional)
          └── Content

v3 中的新功能

Popover.Arrow 组件

在 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 一致:

属性类型默认值描述
isOpenboolean-控制 Popover 的可见性(受控)
defaultOpenbooleanfalse初始打开状态(非受控)
onOpenChange(isOpen: boolean) => void-打开状态变化时触发

自定义渲染函数

Popover.ContentPopover.Arrow 都支持 render prop,让你可以在高级场景下用自定义渲染函数覆盖默认 DOM 元素。

总结

  1. 组件结构:必须使用复合组件(Popover.ContentPopover.Dialog 等)
  2. 触发器:可以使用 Popover.Trigger,或直接将 Button 作为子节点
  3. 内容包装:内容必须放在 Popover.Dialog
  4. 箭头:移除 showArrow prop——改用 Popover.Arrow 子组件
  5. 标题:改用 Popover.Heading 组件
  6. prop 移动位置placementoffsetshouldFlip 移到 Popover.Content
  7. 移除样式 propsizecolorradiusshadow —— 请改用 Tailwind CSS
  8. 移除 backdropbackdrop prop 已移除
  9. 移除 motionmotionProps 已移除,动画机制已不同
  10. 移除 classNames:改在各子组件上使用 className prop

本页目录