coss Sheet 组件实战指南用 Base UI 构建四向侧边面板叠加层【免费下载链接】cosscoss.com/ui is the official design system of Cal.com项目地址: https://gitcode.com/gh_mirrors/or/cosscoss 是 Cal.com 官方设计系统coss.com/ui的开源组件库其 Sheet 组件用于承载设置、详情、工作流等侧边面板类叠加层。本指南以 Sheet 参考文档 为主体结合仓库内 Sheet 完整实现 与p-sheet-1至p-sheet-3示例粒子带你掌握 Sheet 的适用场景、安装导入、最小模式、四向定位、inset 变体、表单嵌入与 Portal 转发并避开常见使用陷阱。何时使用 SheetWhen to use从 Sheet 参考文档 的定义看Sheet 的定位非常明确适合两类场景侧边面板式叠加层用于设置Settings、详情Details、工作流Workflows等需要从主内容区呼出的面板持久上下文面板从主内容区域打开的、需要保持上下文连续性的面板。也就是说Sheet 强调的是从屏幕边缘滑入、不打断主内容流的交互范式与居中的模态对话框Dialog形成互补。何时不要使用 SheetWhen NOT to use文档明确列出了三种用错工具的情况这是选择叠加层组件时的关键判据如果叠加层需要居中并聚焦用户注意力 → 改用 Dialog如果叠加层是仅移动端使用的底部面板→ 改用 Drawer如果流程是破坏性确认如删除账号 → 改用 AlertDialog。从源码结构看Sheet 与 Dialog 共用 Base UI 的Dialog原语见下文实现解析因此它们的行为基座一致区别在于呈现形态与使用语义。安装与依赖文档给出了官方安装方式需要项目已接入 shadcn 风格的 registrynpx shadcnlatest add coss/sheet若手动安装需要补装核心运行时依赖npm install base-ui/react从 sheet.tsx 实现 可以看到Sheet 的底层完全构建在base-ui/react/dialog之上import { Dialog as SheetPrimitive } from base-ui/react/dialog并额外使用了base-ui/react/merge-props与base-ui/react/use-render两个工具模块以及lucide-react关闭按钮图标和库内自带的Button、ScrollArea组件。组件清单与典型导入Sheet 对外暴露的组件即文档中的 Canonical imports共 9 个import { Sheet, // 根组件持有开关状态直接复用 Base UI Dialog.Root SheetContent, // SheetPopup 的别名 SheetDescription, // 无障碍描述映射 Dialog.Description SheetFooter, // 底部操作区分隔线 按钮容器 SheetHeader, // 头部区域标题 描述 SheetPanel, // 可滚动的内容主体 SheetPopup, // 弹出面板本体含方向、变体、关闭按钮 SheetTitle, // 无障碍标题映射 Dialog.Title SheetTrigger, // 打开触发器映射 Dialog.Trigger } from /components/ui/sheet注意/components/ui/sheet是文档中描述的用户侧导入路径在本仓库内组件源码位于 apps/ui/registry/default/ui/sheet.tsx包内组件则发布在 packages/ui/src/components/sheet.tsx。除了上述 9 个常用组件实现文件还导出了SheetPortal、SheetBackdrop别名SheetOverlay、SheetViewport和SheetPrimitive即 Base UI 的 Dialog 原语供需要深层定制的场景使用。关键 API 一览结合 SheetPopup 源码 与 SheetViewport 源码Sheet 的核心配置项如下组件属性类型/取值默认值说明SheetPopupsideright \| left \| top \| bottomright面板滑入方向SheetPopupvariantdefault \| insetdefaultinset在 sm 及以上显示为圆角内嵌卡片SheetPopupshowCloseButtonbooleantrue是否显示右上角 X 关闭按钮SheetPopupclosePropsDialog.Close.Props—透传给关闭按钮的额外属性SheetPopupportalPropsDialog.Portal.Props—转发给内部 Portal见下文 Portal 转发SheetViewportside/variant同上—控制视口栅格布局SheetFootervariantdefault \| baredefaultbare去掉顶部分隔线与背景SheetPanelscrollFadebooleantrue是否启用滚动渐隐效果SheetPanelrenderElementType—Base UI 的 render 提权替换为任意元素从 实现源码 可以看出side还决定了面板的宽度与入场动画left/right侧面板宽度为w-[calc(100%-(--spacing(12)))] max-w-md最大max-w-mdtop/bottom面板为通栏并带border-t/border-b四个方向分别使用translate-x-8/-translate-x-8/translate-y-8/-translate-y-8配合data-starting-style/data-ending-style实现平滑滑入滑出。最小实现模式文档给出的最小模式展示了 Sheet 的完整骨架——触发器、弹出层、头部标题 描述、内容主体、底部操作区与关闭按钮Sheet SheetTriggerOpen/SheetTrigger SheetPopup SheetHeader SheetTitleAre you absolutely sure?/SheetTitle SheetDescription This action cannot be undone. This will permanently delete your account and remove your data from our servers. /SheetDescription /SheetHeader SheetPanelContent/SheetPanel SheetFooter SheetCloseClose/SheetClose /SheetFooter /SheetPopup /Sheet值得说明的是示例中的永久删除账户文案更贴合 AlertDialog 的破坏性确认语义文档将其用作结构示意。实际业务中Sheet 内建议优先放置非破坏性的编辑/详情类内容。内容主体为何自带滚动SheetPanel并非普通 div从 SheetPanel 实现 可以看到它内部包裹了ScrollAreaoverscrollContain 默认开启的scrollFade滚动渐隐因此面板内容超出视口高度时会自动滚动无需额外处理长内容。当同时存在SheetHeader/SheetFooter时面板会自动收窄上下内边距pt-1/pb-1形成紧凑的卡片式排版。四向定位与 inset 变体文档指出 Side options 为top、right、bottom、left默认从右侧滑入。仓库中的 p-sheet-3.tsx 正是这四个方向的完整演示四个 Sheet 分别设置sideright | left | top | bottom并统一使用showCloseButton{false}关闭内置 X 按钮Sheet SheetTrigger render{Button variantoutline /}Open Right/SheetTrigger SheetPopup showCloseButton{false} SheetHeader SheetTitleRight/SheetTitle SheetDescriptionRight side of the screen./SheetDescription /SheetHeader SheetPanel…/SheetPanel /SheetPopup /Sheet实现上四向布局由 SheetViewport 的栅格/弹性样式 驱动bottomgrid grid-rows-[1fr_auto] pt-12面板位于row-start-2上方留出可点击主内容的 12 间距topgrid grid-rows-[auto_1fr] pb-12left/rightflex justify-start/flex justify-end将面板推到对应边缘。inset 变体内嵌圆角面板除四个方向外Sheet 还支持variantinset。仓库中的 p-sheet-2.tsx 演示了该变体SheetPopup variantinset SheetHeader…/SheetHeader SheetPanel classNamegrid gap-4…/SheetPanel SheetFooter…/SheetFooter /SheetPopup从 实现源码 可以看到variantinset在sm≥640px断点以上为面板应用sm:rounded-2xl sm:border并配合before:rounded-[calc(var(--radius-2xl)-1px)]让内描边与圆角吻合同时关闭默认面板自带的内阴影before:hidden。视觉上inset 变体更像悬浮在页面内的圆角卡片而非贴边的通栏面板适合移动端抽屉与桌面端卡片之间无缝切换的场景。实战右侧滑出的表单面板文档给出了从右侧滑出、内嵌表单的经典模式这也是 coss 中设置页最常用的形态。核心在于用render提权把触发器和取消按钮渲染成Button并用Field/Input在SheetPanel内组织表单Sheet SheetTrigger render{Button variantoutline /}Edit Profile/SheetTrigger SheetPopup sideright SheetHeader SheetTitleEdit Profile/SheetTitle SheetDescriptionMake changes to your profile here./SheetDescription /SheetHeader SheetPanel classNameflex flex-col gap-4 Field namename FieldLabelName/FieldLabel Input typetext / /Field /SheetPanel SheetFooter SheetClose render{Button variantghost /}Cancel/SheetClose ButtonSave/Button /SheetFooter /SheetPopup /Sheet仓库中 p-sheet-1.tsx 给出了更完整的可运行版本它将整个SheetPanelSheetFooter包进Form classNamecontents让取消 / 保存按钮与输入框共享同一个表单上下文保存按钮直接typesubmit同时SheetFooter默认带顶部分隔线和bg-muted/72底色见 SheetFooter 源码视觉上天然区分内容区与操作区。Form classNamecontents SheetPanel classNamegrid gap-4 Field FieldLabelName/FieldLabel Input defaultValueMargaret Welsh typetext / /Field Field FieldLabelUsername/FieldLabel Input defaultValuemaggie.welsh typetext / /Field /SheetPanel SheetFooter SheetClose render{Button variantghost /}Cancel/SheetClose Button typesubmitSave/Button /SheetFooter /FormPortal 转发portalProps 深入Sheet 是 coss 中支持Portal 转发的叠加层之一。文档指出SheetPopup接受可选的portalProps直接透传给 Base UI 的Dialog.Portal。相关说明详见仓库中的 portal-props.md。典型用途包括keepMounted让面板内容在关闭后仍保留在 DOM 中配合动画或状态保持场景container把面板渲染到指定 DOM 节点——用于处理层叠上下文stacking context、微前端micro-frontend、Shadow DOM 等特殊宿主环境className/ref等该组件Portal.Props支持的其他属性。SheetPopup portalProps{{ keepMounted: true, container: document.getElementById(overlay-root), }} … /SheetPopup从实现上看portalProps是被 SheetPopup 的 SheetPortal 部分 以展开方式透传的SheetPortal {...portalProps}而SheetPortal即 Base UI 的Dialog.Portal。需要特别注意的是portalProps只影响Portal 节点不影响定位器Positioner如需调整浮层位置应使用side、align、sideOffset等定位属性或在必要场景下自行组合 Base UI 的Positioner。仓库中还声明支持portalProps的叠加层还包括DialogPopup、AlertDialogPopup、DrawerPopup、CommandDialogPopup以及MenuPopup、PopoverPopup、TooltipPopup等浮动层组件不在清单内的组件不会透传该属性。与相邻叠加层组件的配合Sheet 并非孤立存在。文档在Useful particle references中给出了跨叠加层参考p-dialog-1、p-popover-1、p-menu-2。这几个粒子分别对应 p-dialog-1.tsx、p-popover-1.tsx 与 p-menu-2.tsx它们与 Sheet 共享同一套 Base UI 底层与视觉 tokenDialog居中聚焦的模态框用于需要打断主流程的强操作Popover / Menu轻量浮层适合工具提示与快捷菜单Sheet边缘滑入的持久面板适合设置与详情编辑。选择原则可以概括为需要居中强交互用 Dialog需要轻量提示用 Popover需要侧边持久上下文用 Sheet。三者视觉上同源都依赖bg-popover、--color-black/4%描边等 token切换成本很低。常见陷阱Common pitfalls文档总结了三条高频踩坑点结合源码可以进一步解释其成因把简单提示当 Sheet 用SheetPanel内置ScrollArea、SheetPopup内置 Backdropbg-black/32 backdrop-blur-sm见 SheetBackdrop 源码用于 tooltip/popover 级别的轻提示属于明显的重量级误用会遮挡主内容并带来不必要的遮罩缺失关闭动作与焦点回归验证SheetPopup默认渲染aria-labelClose的 X 按钮showCloseButton可关但若你通过showCloseButton{false}关闭它就必须在SheetFooter或面板内自备SheetClose否则用户无法通过可见控件关闭同时应验证打开/关闭一次循环后焦点是否正确归还到触发器Base UI 的 Dialog 原语默认处理焦点陷阱与回归但自定义 render 提权后需自查用 Sheet 硬塞多步骤表单SheetPanel的滚动区域与面板尺寸不适合承载复杂的 wizard 流程文档明确建议这类场景改用独立路由或专门的模态流程避免面板内无限滚动与状态割裂。实用粒子参考清单文档给出的粒子索引便于在仓库中直接查看可运行示例粒子文件主题p-sheet-1p-sheet-1.tsx默认右侧面板 表单Field/Input/提交p-sheet-2p-sheet-2.tsxinset 内嵌圆角变体 表单p-sheet-3p-sheet-3.tsxtop / right / bottom / left 四向演示p-dialog-1p-dialog-1.tsx居中模态对照参考p-popover-1p-popover-1.tsx轻量浮层对照参考p-menu-2p-menu-2.tsx菜单浮层对照参考小结coss Sheet 是一个基于 Base UIDialog构建的四向侧边面板原语默认从右侧滑入支持top/right/bottom/left四个方向与inset圆角变体SheetPanel内置滚动渐隐、SheetFooter支持default/bare两种形态并通过portalProps透传keepMounted、container等 Portal 级能力。使用前请先对照何时不用清单居中交互交给 Dialog、移动端底部面板交给 Drawer、破坏性确认交给 AlertDialog。参考实现源码 sheet.tsx 与 p-sheet-1 ~ p-sheet-3 三个粒子即可快速在业务中落地设置、详情与工作流面板。【免费下载链接】cosscoss.com/ui is the official design system of Cal.com项目地址: https://gitcode.com/gh_mirrors/or/coss创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考