Skip to content
Lenso UI

Popover 弹出框

在由按钮或任意自定义元素触发后,于 portal 中展示丰富内容。

用法

import { Popover } from '@lenso/ui';

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
// Adapted from HeroUI v3.2.6 popover-basic (Apache-2.0).import * as stylex from "@stylexjs/stylex";import { Button, Popover } from "@lenso/ui";import { styles } from "./styles";
export function PopoverBasic() {  return (    <div {...stylex.props(styles.row)}>      <Popover>        <Popover.Trigger render={<Button />}>Click me</Popover.Trigger>        <Popover.Portal>          <Popover.Positioner sideOffset={8}>            <Popover.Popup xstyle={styles.popup}>              <Popover.Title>Popover Title</Popover.Title>              <Popover.Description xstyle={styles.description}>                This is the popover content. You can put any content here.              </Popover.Description>            </Popover.Popup>          </Popover.Positioner>        </Popover.Portal>      </Popover>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

组件结构

import { Popover } from '@lenso/ui';
export default () => (  <Popover>    <Popover.Trigger/>    <Popover.Content>      <Popover.Arrow />      <Popover.Dialog>        <Popover.Heading/>        {/* content goes here */}      </Popover.Dialog>    </Popover.Content>  </Popover>)

示例

带箭头

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
// Adapted from HeroUI v3.2.6 popover-with-arrow (Apache-2.0).import { Ellipsis } from "@gravity-ui/icons";import * as stylex from "@stylexjs/stylex";import { Button, Popover } from "@lenso/ui";import { styles } from "./styles";
export function PopoverWithArrow() {  return (    <div {...stylex.props(styles.row)}>      <Popover>        <Popover.Trigger render={<Button variant="secondary" />}>With Arrow</Popover.Trigger>        <Popover.Portal>          <Popover.Positioner sideOffset={8}>            <Popover.Popup xstyle={styles.popup}>              <Popover.Arrow />              <Popover.Title>Popover with Arrow</Popover.Title>              <Popover.Description xstyle={styles.description}>                The arrow shows which element triggered the popover.              </Popover.Description>            </Popover.Popup>          </Popover.Positioner>        </Popover.Portal>      </Popover>      <Popover>        <Popover.Trigger          render={<Button isIconOnly aria-label="More options" variant="tertiary" />}        >          <Button.Icon>            <Ellipsis />          </Button.Icon>        </Popover.Trigger>        <Popover.Portal>          <Popover.Positioner sideOffset={10}>            <Popover.Popup xstyle={styles.popup}>              <Popover.Arrow />              <Popover.Title>Popover with Arrow</Popover.Title>              <Popover.Description xstyle={styles.description}>                The arrow shows which element triggered the popover.              </Popover.Description>            </Popover.Popup>          </Popover.Positioner>        </Popover.Portal>      </Popover>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

可交互内容

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
// Adapted from HeroUI v3.2.6 popover-interactive (Apache-2.0).import * as stylex from "@stylexjs/stylex";import { Avatar, Button, Popover } from "@lenso/ui";import { useState } from "react";import { styles } from "./styles";
export function PopoverInteractive() {  const [isFollowing, setIsFollowing] = useState(false);  return (    <div {...stylex.props(styles.profileRow)}>      <Popover>        <Popover.Trigger aria-label="User profile">          <div {...stylex.props(styles.identity)}>            <Avatar size="sm">              <Avatar.Image                alt="Sarah Johnson"                src="https://img.heroui.chat/image/avatar?w=400&h=400&u=1"              />              <Avatar.Fallback>SJ</Avatar.Fallback>            </Avatar>            <div {...stylex.props(styles.identityText)}>              <p {...stylex.props(styles.name)}>Sarah Johnson</p>              <p {...stylex.props(styles.handle)}>@sarahj</p>            </div>          </div>        </Popover.Trigger>        <Popover.Portal>          <Popover.Positioner sideOffset={8}>            <Popover.Popup xstyle={styles.profilePopup}>              <Popover.Title render={<div />}>                <div {...stylex.props(styles.profileHeading)}>                  <div {...stylex.props(styles.identityLarge)}>                    <Avatar size="md">                      <Avatar.Image                        alt="Sarah Johnson"                        src="https://img.heroui.chat/image/avatar?w=400&h=400&u=1"                      />                      <Avatar.Fallback>SJ</Avatar.Fallback>                    </Avatar>                    <div>                      <p {...stylex.props(styles.strong)}>Sarah Johnson</p>                      <p {...stylex.props(styles.muted)}>@sarahj</p>                    </div>                  </div>                  <Button                    xstyle={styles.follow}                    size="sm"                    variant={isFollowing ? "tertiary" : "primary"}                    onClick={() => setIsFollowing(!isFollowing)}                  >                    {isFollowing ? "Following" : "Follow"}                  </Button>                </div>              </Popover.Title>              <Popover.Description xstyle={styles.bio}>                Product designer and creative director. Building beautiful experiences that matter.              </Popover.Description>              <div {...stylex.props(styles.statistics)}>                <div>                  <span {...stylex.props(styles.strong)}>892</span>                  <span {...stylex.props(styles.statisticLabel)}>Following</span>                </div>                <div>                  <span {...stylex.props(styles.strong)}>12.5K</span>                  <span {...stylex.props(styles.statisticLabel)}>Followers</span>                </div>              </div>            </Popover.Popup>          </Popover.Positioner>        </Popover.Portal>      </Popover>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

位置

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
// Adapted from HeroUI v3.2.6 popover-placement (Apache-2.0).import * as stylex from "@stylexjs/stylex";import { Button, Popover } from "@lenso/ui";import { styles } from "./styles";
export function PopoverPlacement() {  return (    <div {...stylex.props(styles.grid)}>      <div />      <Popover>        <Popover.Trigger render={<Button xstyle={styles.fullWidth} variant="tertiary" />}>          Top        </Popover.Trigger>        <Popover.Portal>          <Popover.Positioner side="top" sideOffset={8}>            <Popover.Popup>              <Popover.Arrow />              <p {...stylex.props(styles.small)}>Top placement</p>            </Popover.Popup>          </Popover.Positioner>        </Popover.Portal>      </Popover>      <div />      <Popover>        <Popover.Trigger render={<Button xstyle={styles.fullWidth} variant="tertiary" />}>          Left        </Popover.Trigger>        <Popover.Portal>          <Popover.Positioner side="left" sideOffset={8}>            <Popover.Popup>              <Popover.Arrow />              <p {...stylex.props(styles.small)}>Left placement</p>            </Popover.Popup>          </Popover.Positioner>        </Popover.Portal>      </Popover>      <div {...stylex.props(styles.center)}>        <span {...stylex.props(styles.muted)}>Click buttons</span>      </div>      <Popover>        <Popover.Trigger render={<Button xstyle={styles.fullWidth} variant="tertiary" />}>          Right        </Popover.Trigger>        <Popover.Portal>          <Popover.Positioner side="right" sideOffset={8}>            <Popover.Popup>              <Popover.Arrow />              <p {...stylex.props(styles.small)}>Right placement</p>            </Popover.Popup>          </Popover.Positioner>        </Popover.Portal>      </Popover>      <div />      <Popover>        <Popover.Trigger render={<Button xstyle={styles.fullWidth} variant="tertiary" />}>          Bottom        </Popover.Trigger>        <Popover.Portal>          <Popover.Positioner side="bottom" sideOffset={8}>            <Popover.Popup>              <Popover.Arrow />              <p {...stylex.props(styles.small)}>Bottom placement</p>            </Popover.Popup>          </Popover.Positioner>        </Popover.Portal>      </Popover>      <div />    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

渲染函数

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
// Adapted from HeroUI v3.2.6 popover-render-function (Apache-2.0).import * as stylex from "@stylexjs/stylex";import { Button, Popover } from "@lenso/ui";import { styles } from "./styles";
export function RenderFunction() {  return (    <div {...stylex.props(styles.row)}>      <Popover>        <Popover.Trigger render={<Button />}>Click me</Popover.Trigger>        <Popover.Portal>          <Popover.Positioner sideOffset={8}>            <Popover.Popup              xstyle={styles.popup}              render={(props) => <div {...props} data-custom="foo" />}            >              <Popover.Title>Popover Title</Popover.Title>              <Popover.Description xstyle={styles.description}>                This is the popover content. You can put any content here.              </Popover.Description>            </Popover.Popup>          </Popover.Positioner>        </Popover.Portal>      </Popover>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

自定义样式

Tailwind CSS

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
// Adapted from HeroUI v3.2.6 popover-custom-styles (Apache-2.0).import * as stylex from "@stylexjs/stylex";import { Button, Popover } from "@lenso/ui";import { styles } from "./styles";
export function CustomStyles() {  return (    <Popover>      <Popover.Trigger render={<Button variant="secondary" />}>Details</Popover.Trigger>      <Popover.Portal>        <Popover.Positioner sideOffset={8}>          <Popover.Popup xstyle={styles.customPopup}>            <div {...stylex.props(styles.customDialog)}>              <div aria-hidden="true" {...stylex.props(styles.highlight)} />              <Popover.Title xstyle={styles.customHeading}>Keyboard shortcuts</Popover.Title>              <dl {...stylex.props(styles.shortcuts)}>                <div {...stylex.props(styles.shortcut)}>                  <dt {...stylex.props(styles.muted)}>Save</dt>                  <dd {...stylex.props(styles.key)}>⌘ S</dd>                </div>                <div {...stylex.props(styles.shortcut)}>                  <dt {...stylex.props(styles.muted)}>Search</dt>                  <dd {...stylex.props(styles.key)}>⌘ K</dd>                </div>              </dl>            </div>          </Popover.Popup>        </Popover.Positioner>      </Popover.Portal>    </Popover>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

全局 CSS

若要自定义组件类,可使用 @layer components 指令。了解更多。

@layer components {  .popover {    @apply rounded-xl shadow-2xl;  }
  .popover__dialog {    @apply p-4;  }
  .popover__heading {    @apply text-lg font-bold;  }}

样式参考

HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。

CSS 类

Popover 使用以下 CSS 类(查看源码样式):

基础类 [!toc]

  • .popover - Popover 根容器样式
  • .popover__dialog - 对话框内容包裹层
  • .popover__heading - 标题文本样式
  • .popover__trigger - 触发元素样式

交互状态

组件支持以下动画相关状态:

  • 进入:[data-entering] — Popover 出现过程中应用
  • 离开:[data-exiting] — Popover 消失过程中应用
  • 位置:[data-placement="*"] — 根据 Popover 位置应用
  • 焦点::focus-visible 或 [data-focus-visible="true"]

API 参考

Popover

Prop类型默认值描述
childrenReact.ReactNode-触发器与内容元素
isOpenboolean-控制 Popover 是否可见(受控)
defaultOpenbooleanfalse初始打开状态(非受控)
onOpenChange(isOpen: boolean) => void-打开状态变化时调用

Popover.Content

Prop类型默认值描述
childrenReact.ReactNode-在 Popover 中展示的内容
placement"top" | "bottom" | "left" | "right" (及变体)"bottom"Popover 的位置
offsetnumber8与触发元素的距离
shouldFlipbooleantrue是否允许 Popover 改变方向以适配空间
classNamestring-额外的 CSS 类名
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, PopoverRenderProps>-通过自定义渲染函数覆盖默认的 DOM 元素。

Popover.Dialog

Prop类型默认值描述
childrenReact.ReactNode-对话框内容
classNamestring-额外的 CSS 类名

Popover.Trigger

Prop类型默认值描述
childrenReact.ReactNode-触发 Popover 的元素
classNamestring-额外的 CSS 类名

Popover.Arrow

Prop类型默认值描述
childrenReact.ReactNode-自定义箭头元素
classNamestring-额外的 CSS 类名
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, OverlayArrowRenderProps>-通过自定义渲染函数覆盖默认的 DOM 元素。

相关组件