JGuang

弹出面板

Popover · Astryx

交互预览
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

弹出面板 · Popover

在触发元素附近显示交互面板。

安装与前置条件

npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

需要 React 19+,按顺序导入基础 CSS 和主题,并设置 Theme Provider。参见开始使用。

示例与使用方式

  • 弹出面板 · 综合展示 1:首先体验这个示例,再查看代码理解组件的组合方式。
  • 弹出面板 · 交互示例 2:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 弹出面板 · 交互示例 3:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 弹出面板 · 筛选 4:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 弹出面板 · 交互示例 5:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 弹出面板 · 键盘操作 6:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 弹出面板 · 交互示例 7:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。

API 与上游详细参考

优先使用 0.7.1 官方中文说明;上游尚未提供中文的条目保留英文。属性名、类型及默认值保持原生 API,不把示例状态名称当成组件属性。

Popover

A click-triggered overlay anchored to a button or trigger element. Use it for secondary actions, inline confirmations, or supplementary information that does not warrant a full dialog. For hover previews use HoverCard, for brief helper text use Tooltip.

使用建议

  • Keep popover content focused on a single task or piece of information.
  • Provide a clear way to close: either by clicking outside or with an explicit close button.
  • Theme the painted surface through the canonical popover target.
  • 避免:Nest popovers inside other popovers; it creates confusing focus and navigation.
  • 避免:Assume input complexity alone determines the presentation; evaluate the task's focus, space, and interaction requirements.
  • 避免:Assume scrolling alone means Popover is the wrong component; a bounded Popover may scroll while a focused anchored interaction remains appropriate.

Flush surface for a list of rows

<Popover
  label="Recent files"
  padding={0}
  content={
    <List>
      <ListItem label="Quarterly report.pdf" />
      <ListItem label="Roadmap.key" />
    </List>
  }>
  <Button label="Recent" variant="secondary" />
</Popover>

Roomier surface for a form

<Popover
  label="Save search"
  padding={4}
  content={<SaveSearchForm />}>
  <Button label="Save search" variant="secondary" />
</Popover>

主题 API

{
  "targets": [
    {
      "className": "astryx-popover"
    }
  ],
  "vars": [
    {
      "name": "--_popover-radius",
      "description": "Border radius of the popover surface",
      "default": "var(--radius-container)",
      "private": true
    }
  ],
  "derived": [
    {
      "property": "borderRadius",
      "vars": [
        "--_popover-radius"
      ]
    }
  ]
}

Popover

一个点击触发的弹出框,用于显示锚定到触发元素的交互式内容。

属性类型默认值说明
childrenReactNode触发元素。必须包含一个 <button> 或 [role="button"] 元素。
anchorRefReact.RefObject<HTMLElement>在兄弟模式下用作弹出框锚点的外部 ref。
content *ReactNode在弹出框内显示的内容。
placement'above' | 'below' | 'start' | 'end''below'相对于触发器的位置放置方式。逻辑值:start/end 根据弹出层自身继承的方向解析,RTL 环境通过纯 CSS 自动镜像。
alignment'start' | 'center' | 'end''start'沿放置轴的对齐方式。逻辑值:start/end 跟随弹出层自身继承的方向(RTL 镜像)。
isOpenboolean在受控模式下弹出框是否显示。
onOpenChange(isOpen: boolean) => void弹出框可见性变化时触发的回调。
isEnabledbooleantrue设为 false 时,忽略触发器交互。
widthnumber | string'auto'弹出框容器的宽度。弹出层仍会限制在视口和安全区域留白内,长内容再滚动。
padding0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 103弹出框表面的内边距,使用间距刻度(0、0.5、1、1.5、2、3、4、5、6、8、10),与 Card 和 Stack 的 padding 属性一致。当内容自行管理边缘(如行列表或带分隔线的标题)时传入 0 使表面无内边距,并由内容自行设置内边距。
labelstring弹出框对话框的无障碍标签。
role'dialog' | 'none''dialog'弹出框包装器的 ARIA 角色。对话框式弹出框使用 dialog;当内容提供自己的角色(如 menu 或 listbox)时使用 none。
isModalbooleantrue对话框式弹出框是否设置 aria-modal。仅在 role 为 dialog 时适用。
hasCloseButtonbooleantrue是否包含用于无障碍访问的隐藏关闭按钮。
closeButtonLabelstring'Close popover'隐藏关闭按钮的标签。
hasAutoFocusbooleantrue弹出框打开时是否将焦点移入其中。优先聚焦调用方内容中的第一个控件;若对话框没有此类控件,则聚焦带标签的表面。生成的关闭按钮仅在键盘导航到达时显示。
hasLightDismissbooleantrue点击外部是否关闭弹出框。需要显式关闭的界面(如新手引导提示)设为 false。
hasEscapeDismissbooleantrue按 Escape 是否关闭弹出框。仅在 hasLightDismiss={false} 时生效,因为原生 light dismiss 行为同样响应 Escape。
xstyleStyleXStylesStyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value, not an inline style object like style={{}}.

组件结构

  • Trigger element: Caller-supplied or externally referenced control that anchors and toggles the popover.
  • Popover surface: Painted surface owned and themed by Popover through the canonical popover target.
  • Popover content: Caller-supplied content rendered inside the surface.
  • Fallback close control: Keyboard-reachable close affordance appended by usePopover when enabled.

usePopover

Headless hook for click-triggered popovers with focus trapping. Combines useLayer with useFocusTrap, auto-focus, light dismiss, Escape handling, and an optional hidden close button for accessible dialog-like popover behavior. Every painted surface emits the canonical popover target. A custom composition needing a distinct stable seam should pass and document its own surfaceTarget.

Parameters

ParameterTypeDescription
onShow() => voidCallback fired when the popover becomes visible.
onHide() => voidCallback fired when the popover is hidden. Use this to return focus to the trigger when needed.
xstyleStyleXStylesStyleX styles applied to the popover content wrapper, after the default surface styles.
hasLightDismissbooleanWhether clicking outside dismisses the popover.
hasEscapeDismissbooleanWhether pressing Escape dismisses the popover. Only takes full effect together with hasLightDismiss: false, since native light dismiss also closes on Escape.
hasAutoFocusbooleanWhether to focus the first genuine content control when opened. Dialogs with none fall back to the labeled surface; the generated close control is excluded from initial focus.
hasCloseButtonbooleanWhether to include a hidden close button that appears for keyboard users.
closeButtonLabelstringAccessible label for the hidden close button.
dialogLabelstringAccessible label for the popover dialog (only applies when role is "dialog"). Provide one when there is no visible title.
role'dialog' | 'none'ARIA role on the content wrapper. Use "dialog" for genuine dialog content; use "none" for listbox/menu popups whose own content role should be exposed and whose trigger keeps DOM focus.
isModalbooleanWhether a dialog-role popover is modal (aria-modal). Only applies when role is "dialog".
hasSurfacebooleanWhether to apply the default popover surface background, radius, and shadow.
padding0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10Inner padding of the painted surface on the spacing scale (0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10). Omit it and the hook paints no padding of its own; Popover passes 3 by default and 0 for a flush surface.
surfaceTargetstringOptional component-owned refinement target on the painted surface, without the astryx- prefix. Use and document one when a direct hook composition needs distinct theme reachability.

Returns

[
  {
    "name": "triggerRef",
    "type": "(el: HTMLElement | null) => void",
    "description": "Ref callback to attach to the trigger element for CSS anchor positioning."
  },
  {
    "name": "contentRef",
    "type": "RefObject<HTMLDivElement | null>",
    "description": "Ref for the popover content container used by focus trapping."
  },
  {
    "name": "anchorId",
    "type": "string",
    "description": "CSS anchor name for advanced positioning cases."
  },
  {
    "name": "show",
    "type": "(options?: {skipAutoFocus?: boolean}) => void",
    "description": "Imperatively show the popover. skipAutoFocus preserves current focus for input-triggered popovers."
  },
  {
    "name": "hide",
    "type": "() => void",
    "description": "Imperatively hide the popover."
  },
  {
    "name": "toggle",
    "type": "() => void",
    "description": "Toggle the popover open or closed."
  },
  {
    "name": "isOpen",
    "type": "boolean",
    "description": "Whether the popover is currently open."
  },
  {
    "name": "id",
    "type": "string",
    "description": "Unique ID for aria-describedby or aria-controls."
  },
  {
    "name": "render",
    "type": "(children: ReactNode, props?: ContextRenderProps) => ReactNode",
    "description": "Render function for anchor-positioned popover content. Pass placement and alignment here. Logical: start/end resolve against the popover's own inherited direction (RTL mirrors in pure CSS)."
  },
  {
    "name": "triggerProps",
    "type": "{aria-haspopup: \"dialog\" | \"true\"; aria-expanded: boolean; aria-controls: string}",
    "description": "ARIA attributes to spread onto the trigger element. aria-haspopup reflects the popover role."
  }
]

使用建议

  • Use for interactive content such as menus, pickers, forms, and command panels that need focus management.
  • Prefer the Popover component for standard trigger-content pairs; use the hook for custom trigger patterns.
  • Use popover as the broad canonical surface target.
  • When a custom composition needs its own theme refinement, pass and document an owned surfaceTarget such as selector-popup. It refines the Popover surface rather than creating another anatomy part.
  • 避免:Use for non-interactive hover previews: use useHoverCard or useTooltip instead.

完整示例的额外依赖

部分示例使用独立图标包。示例清单中的每条安装命令包含该示例实际需要的依赖;若要运行本页全部示例,还需安装:

npm install @heroicons/react@2.2.0

示例的 StyleX 编译要求

PopoverBottomSheetAlternative 包含 stylex.create,需要配置 StyleX 源码编译流程。仅引入 Core 预编译 CSS 不足以运行这些示例样式,复制前请阅读样式与 Tailwind。