跳到主要内容

Panel 悬浮面板Panel

停靠在一侧的非模态卡片:没有遮罩、不锁滚动、不圈焦点,打开时页面其余部分照常可用。用于检查器、筛选面板这类“边看边调”的辅助区域。需要人先处理完才能继续时用 Drawer。

同一张悬浮卡片

Dialog、Drawer、Sheet、Panel 不是四套东西,而是同一张悬浮卡片(FloatingCard)在不同位置、不同尺寸下的用法:一张圆角卡片,和视口四周留一圈缝,从停靠的那一侧滑入。没有阴影,模态时靠遮罩压暗背景,非模态时靠描边和页面分开。遮罩、焦点圈、滚动锁、Esc、进退场都在 FloatingCard 里,只此一份;卡片里面统一用 FloatingHeader / FloatingBody / FloatingFooter 三个结构件来搭。

组件停靠位置模态用在哪
Dialog居中模态确认、简短的表单
Drawer贴着四边之一模态详情、较长的表单、导航
Sheet贴着底边模态手机上代替对话框和抽屉
Panel 本页贴着四边之一非模态检查器、筛选面板

结构件,以及限制在一个区域里

面板默认停靠在视口边上。传 container 和 contained 可以把它限制在某个容器里(该容器需要 position: relative)——下面的面板就停靠在演示框的右边,而不是整个页面。里面同样用 FloatingHeader / FloatingBody / FloatingFooter 来搭。

画布面板打开时,这里的按钮和开关照常可用。

位置与尺寸

placement 是停靠的那一侧,默认 right。size 是主轴尺寸:左右是宽度 sm 280、md 320(默认)、lg 400;上下是高度 sm 200、md 280、lg 400。尺寸不会超过容器减去间隙。

停靠在页面上

不传 container 时面板停靠在视口边上,浮在页面内容之上。打开它不会抢走焦点;焦点在面板里时按 Esc 关闭,并把焦点还给进来之前的元素。面板会盖住它下面的内容,所以通常要给页面留出相应的空位,或者让面板可以收起。

接口

Panel

属性类型默认值说明
placement'left' | 'right' | 'top' | 'bottom''right'停靠在哪一侧。
size'sm' | 'md' | 'lg' | number | string'md'主轴尺寸。左右是宽度 280 / 320 / 400;上下是高度 200 / 280 / 400。
role'complementary' | 'region' | 'dialog''complementary'语义:页面的辅助区域、普通区域,或非模态对话框。
containedboolean—配合 container:把面板限制在该容器内(容器需要 position: relative)。
stretchbooleantrue是否在另一个方向上撑满;false 则按内容大小并居中。
open / defaultOpenbooleanfalse开合,受控 / 非受控。
onOpenChange(open: boolean) => void—开合变化时(Esc、点遮罩、关闭按钮、拖拽关闭都会触发)。
dismissiblebooleantrue允许 Esc 和点遮罩关闭。
gapnumber12(窄屏 8)卡片到视口边缘的间隙(px)。
initialFocusRefObject<HTMLElement>—模态时打开后焦点落在哪。默认是卡片里带 data-autofocus 的元素,没有就落在卡片本身。
restoreFocusbooleantrue关闭后把焦点还给打开前的元素。
containerHTMLElement | null—渲染到哪个容器,默认 body。
onExited() => void—退场动画结束、节点卸载后。
aria-label / aria-labelledby / aria-describedbystring—不传时自动接上 FloatingHeader 的标题和说明。

同一个组件还以 FloatingPanel 的名字导出,和布局类的“面板”容器重名时用它。

FloatingHeader

属性类型默认值说明
titleReactNode—标题。自动成为卡片的 aria-labelledby。
descriptionReactNode—标题下面的一行说明。自动成为卡片的 aria-describedby。
iconReactNode—标题左边的图标位(40×40 的色块)。
level1 | 2 | 3 | 4 | 5 | 62标题的层级。
closableboolean—是否带关闭按钮。默认跟随卡片的 dismissible。
closeLabelstring'关闭'关闭按钮的读屏名称。
onClose() => void—点关闭按钮时;不传则请求卡片关闭。
childrenReactNode—放在关闭按钮前面的额外操作。

FloatingBody / FloatingFooter

属性类型默认值说明
paddedbooleantrue是否带内边距。内容自己通栏(列表、表格)时关掉。
align'start' | 'end' | 'between' | 'stretch''end'按钮的排法:靠左、靠右、两端、等分撑满。

无障碍

  • 默认是 role="complementary"(辅助地标),名字取自 FloatingHeader 的标题;没有标题时必须给 aria-label。一页里有多个辅助地标时名字要各不相同。
  • 非模态:没有 aria-modal,不圈焦点,打开时也不移动焦点。请让触发按钮带 aria-expanded,并让面板在 DOM 或 Tab 顺序上容易到达。
  • 焦点在面板里时 Esc 关闭,焦点还给进面板之前所在的元素;焦点在面板外时 Esc 不归它管,不会抢页面上别处的 Esc。
  • 面板渲染在 Portal 里(默认挂到 body 末尾):键盘用户要 Tab 过整页才能到它。内容重要时用 container 把它放到触发按钮附近,或打开后主动把焦点移进去。
  • 没有遮罩,靠 1px 的 --ok-line-2 描边和页面分开,深浅色下都看得清。