Components

弹出框

在一个门户中通过按钮触发显示丰富的内容。

import * as React from "react";
import { Popover } from "radix-ui";
import { MixerHorizontalIcon, Cross2Icon } from "@radix-ui/react-icons";
import "./styles.css";
const PopoverDemo = () => (
<Popover.Root>
<Popover.Trigger asChild>
<button className="IconButton" aria-label="Update dimensions">
<MixerHorizontalIcon />
</button>
</Popover.Trigger>
<Popover.Portal>
<Popover.Content className="PopoverContent" sideOffset={5}>
<div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
<p className="Text" style={{ marginBottom: 10 }}>
Dimensions
</p>
<fieldset className="Fieldset">
<label className="Label" htmlFor="width">
Width
</label>
<input className="Input" id="width" defaultValue="100%" />
</fieldset>
<fieldset className="Fieldset">
<label className="Label" htmlFor="maxWidth">
Max. width
</label>
<input className="Input" id="maxWidth" defaultValue="300px" />
</fieldset>
<fieldset className="Fieldset">
<label className="Label" htmlFor="height">
Height
</label>
<input className="Input" id="height" defaultValue="25px" />
</fieldset>
<fieldset className="Fieldset">
<label className="Label" htmlFor="maxHeight">
Max. height
</label>
<input className="Input" id="maxHeight" defaultValue="none" />
</fieldset>
</div>
<Popover.Close className="PopoverClose" aria-label="Close">
<Cross2Icon />
</Popover.Close>
<Popover.Arrow className="PopoverArrow" />
</Popover.Content>
</Popover.Portal>
</Popover.Root>
);
export default PopoverDemo;

Features

    可以是可控或不可控的。

    自定义侧边、对齐、偏移、碰撞处理。

    可选择性地渲染指向箭头。

    完全管理和自定义焦点。

    支持模态和非模态模式。

    自定义处理关闭和层叠行为。

安装

通过命令行安装组件。

npm install @radix-ui/react-popover

结构

导入所有部分并组合在一起。

import { Popover } from "radix-ui";
export default () => (
<Popover.Root>
<Popover.Trigger />
<Popover.Anchor />
<Popover.Portal>
<Popover.Content>
<Popover.Close />
<Popover.Arrow />
</Popover.Content>
</Popover.Portal>
</Popover.Root>
);

API 参考

包含弹出框的所有部分。

PropTypeDefault
defaultOpen
boolean
No default value
open
boolean
No default value
onOpenChange
function
No default value
modal
boolean
false

触发器

切换弹出框的按钮。默认情况下,Popover.Content 将相对于触发器定位。

PropTypeDefault
asChild
boolean
false
Data attributeValues
[data-state]"open" | "closed"

可选元素,用于将Popover.Content 定位。如果未使用此部分,内容将相对于 Popover.Trigger 定位。

PropTypeDefault
asChild
boolean
false

门户

使用时,将内容部分门户到 body

PropTypeDefault
forceMount
boolean
No default value
container
HTMLElement
document.body

内容

在弹出框打开时弹出的组件。

PropTypeDefault
asChild
boolean
false
onOpenAutoFocus
function
No default value
onCloseAutoFocus
function
No default value
onEscapeKeyDown
function
No default value
onPointerDownOutside
function
No default value
onFocusOutside
function
No default value
onInteractOutside
function
No default value
forceMount
boolean
No default value
side
enum
"bottom"
sideOffset
number
0
align
enum
"center"
alignOffset
number
0
avoidCollisions
boolean
true
collisionBoundary
Boundary
[]
collisionPadding
number | Padding
0
arrowPadding
number
0
sticky
enum
"partial"
hideWhenDetached
boolean
false
Data attributeValues
[data-state]"open" | "closed"
[data-side]"left" | "right" | "bottom" | "top"
[data-align]"start" | "end" | "center"
CSS VariableDescription
--radix-popover-content-transform-origin从内容和箭头位置/偏移量计算的 transform-origin
--radix-popover-content-available-width触发器和边界边缘之间的剩余宽度
--radix-popover-content-available-height触发器和边界边缘之间的剩余高度
--radix-popover-trigger-width触发器的宽度
--radix-popover-trigger-height触发器的高度

箭头

可选的箭头元素,与弹出框一起渲染。这可以用来帮助视觉上将锚与 Popover.Content 进行连接。必须在 Popover.Content 内部渲染。

PropTypeDefault
asChild
boolean
false
width
number
10
height
number
5

关闭

关闭打开的弹出框的按钮。

PropTypeDefault
asChild
boolean
false

示例

限制内容大小

您可能想要限制内容的宽度以匹配触发器的宽度。您还可能想要限制其高度以不超过视口。

我们提供了多个 CSS 自定义属性,如 --radix-popover-trigger-width--radix-popover-content-available-height 来支持此功能。使用它们来限制内容的尺寸。

// index.jsx
import { Popover } from "radix-ui";
import "./styles.css";
export default () => (
<Popover.Root>
<Popover.Trigger></Popover.Trigger>
<Popover.Portal>
<Popover.Content className="PopoverContent" sideOffset={5}>
</Popover.Content>
</Popover.Portal>
</Popover.Root>
);
/* styles.css */
.PopoverContent {
width: var(--radix-popover-trigger-width);
max-height: var(--radix-popover-content-available-height);
}

基于原点的动画

我们提供了一个 CSS 自定义属性 --radix-popover-content-transform-origin。使用它可以根据 sidesideOffsetalignalignOffset 以及任何碰撞动画内容。

// index.jsx
import { Popover } from "radix-ui";
import "./styles.css";
export default () => (
<Popover.Root>
<Popover.Trigger></Popover.Trigger>
<Popover.Portal>
<Popover.Content className="PopoverContent"></Popover.Content>
</Popover.Portal>
</Popover.Root>
);
/* styles.css */
.PopoverContent {
transform-origin: var(--radix-popover-content-transform-origin);
animation: scaleIn 0.5s ease-out;
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0);
}
to {
opacity: 1;
transform: scale(1);
}
}

基于碰撞的动画

我们提供了 data-sidedata-align 属性。它们的值会在运行时更改以反映碰撞。使用它们可以创建与碰撞和方向相关的动画。

// index.jsx
import { Popover } from "radix-ui";
import "./styles.css";
export default () => (
<Popover.Root>
<Popover.Trigger></Popover.Trigger>
<Popover.Portal>
<Popover.Content className="PopoverContent"></Popover.Content>
</Popover.Portal>
</Popover.Root>
);
/* styles.css */
.PopoverContent {
animation-duration: 0.6s;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.PopoverContent[data-side="top"] {
animation-name: slideUp;
}
.PopoverContent[data-side="bottom"] {
animation-name: slideDown;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

使用自定义锚

如果您不想使用触发器作为锚,可以将内容锚定到另一个元素。

// index.jsx
import { Popover } from "radix-ui";
import "./styles.css";
export default () => (
<Popover.Root>
<Popover.Anchor asChild>
<div className="Row">
行作为锚 <Popover.Trigger>触发器</Popover.Trigger>
</div>
</Popover.Anchor>
<Popover.Portal>
<Popover.Content></Popover.Content>
</Popover.Portal>
</Popover.Root>
);
/* styles.css */
.Row {
background-color: gainsboro;
padding: 20px;
}

可访问性

遵循 对话框 WAI-ARIA 设计模式

键盘交互

KeyDescription
Space
打开/关闭弹出框。
Enter
打开/关闭弹出框。
Tab
将焦点移动到下一个可聚焦元素
Shift + Tab
将焦点移动到上一个可聚焦元素
Esc
关闭弹出框并将焦点移到 Popover.Trigger

自定义 API

通过将原始部分抽象为您自己的组件来创建自己的 API。

抽象箭头并设置默认配置

此示例将 Popover.Arrow 部分抽象出来,并设置默认的 sideOffset 配置。

使用

import { Popover, PopoverTrigger, PopoverContent } from "./your-popover";
export default () => (
<Popover>
<PopoverTrigger>弹出框触发器</PopoverTrigger>
<PopoverContent>弹出框内容</PopoverContent>
</Popover>
);

实现

// your-popover.jsx
import * as React from "react";
import { Popover as PopoverPrimitive } from "radix-ui";
export const Popover = PopoverPrimitive.Root;
export const PopoverTrigger = PopoverPrimitive.Trigger;
export const PopoverContent = React.forwardRef(
({ children, ...props }, forwardedRef) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content sideOffset={5} {...props} ref={forwardedRef}>
{children}
<PopoverPrimitive.Arrow />
</PopoverPrimitive.Content>
</PopoverPrimitive.Portal>
),
);