Radix Primitives Collapsible 组件变更史:从 1.1.5 到 1.1.20 的工程演进与实现原理
前端UI组件【免费下载链接】primitivesRadix Primitives is an open-source UI component library for building high-quality, accessible design systems and web apps. Maintained by workos.项目地址https://gitcode.com/gh_mirrors/pr/primitives点击查看免费下载Radix Primitives 是开源的 React 无障碍 UI 组件库由 WorkOS 维护其中radix-ui/react-collapsible提供了折叠面板Collapsible这一基础交互组件。packages/react/collapsible/CHANGELOG.md 完整记录了该组件从 1.1.5 到 1.1.20 共 16 个版本的演进涵盖 React Server Components 兼容性、构建产物 provenance 认证、tree-shaking 优化、aria-controls行为修复、useControllableState性能改进等关键工程决策。本文以该变更日志为主线结合仓库内的源码与测试带你理解 Collapsible 的受控状态机制、Presence 动画生命周期、无障碍语义设计以及 Radix 版本治理与工程基建的细节。读完你将掌握如何正确使用 Collapsible 的三种组件与受控/非受控模式如何利用--radix-collapsible-content-height/width实现开合动画以及各版本升级背后的实际收益与兼容性注意点。Collapsible 组件家族Root、Trigger 与 Content 的分工Collapsible 由三个子组件组成从 源码入口 可看到导出关系Collapsible.Root最外层容器持有open状态并向下通过 Context 分发内部渲染为Primitive.div带有data-stateopen/closed与data-disabled属性。Collapsible.Trigger用户点击的开关按钮内部渲染为Primitive.button自动设置typebutton、aria-controls、aria-expanded、data-state、data-disabled与disabled并通过composeEventHandlers将自定义onClick与内置的开合逻辑合并而非替换。Collapsible.Content折叠内容区域内部渲染为Primitive.div通过 Presence 控制挂载/卸载时机支持forceMount属性。一个最小可运行示例对应 SSR 测试页import * as React from react; import { Collapsible } from radix-ui; export default function Page() { return ( Collapsible.Root Collapsible.TriggerTrigger/Collapsible.Trigger Collapsible.ContentContent/Collapsible.Content /Collapsible.Root ); }受控与非受控模式Root 的三个核心 API从 CollapsibleProps 接口 可以看到 Root 支持三个与状态相关的 Props属性类型作用defaultOpenboolean非受控模式下的初始开合状态未设置时默认false代码中defaultProp: defaultOpen ?? falseopenboolean受控模式下完全由外部状态驱动的开合值onOpenChange(open: boolean) void状态变化回调在非受控模式下可用来监听变化Root 内部通过useControllableState来自radix-ui/react-use-controllable-state统一处理这两种模式传入open即为受控否则回退到defaultOpen维护内部状态。测试用例 验证了受控模式下的关键行为点击 Trigger 会调用onOpenChange(false)但内容不会关闭因为状态由外部open决定而非受控模式点击后会同时触发onOpenChange且内容随之关闭。受控模式的使用示例对应 Storybook 的 Controlled 示例export const Controlled () { const [open, setOpen] React.useState(false); return ( Collapsible.Root open{open} onOpenChange{setOpen} Collapsible.Trigger{open ? close : open}/Collapsible.Trigger Collapsible.ContentContent 1/Collapsible.Content /Collapsible.Root ); };无障碍语义aria-controls、aria-expanded 与 1.1.13 的修复Collapsible 是 Radix 无障碍优先理念的典型体现。Trigger 在 渲染时 自动注入aria-expanded{context.open || false}告知屏幕阅读器当前展开状态aria-controls{context.open ? context.contentId : undefined}当内容挂载时才引用其 ID内容关闭未挂载时该属性不渲染。1.1.13 版本修复的正是后者此前 Trigger 会在内容已从 DOM 移除时仍通过aria-controls引用一个不存在的元素。修复后的行为被 collapsible.test.tsx 的 aria-controls 测试组 覆盖内容未挂载时 Trigger 不含aria-controls内容挂载后 Trigger 的aria-controls指向真实存在的内容节点。同时该版本为所有 package.json 增加了repository.directory字段见 package.json以提升包元数据的可追溯性。此外 Content 节点会携带hidden属性与data-stateRoot 与 Trigger 也都会映射data-disabled方便样式定制详见后文。动画与 Presence--radix-collapsible-content-* 的测量机制Collapsible 的开合动画之所以能流畅运行关键在于 Content 实现 CollapsibleContentImpl 的尺寸测量逻辑通过getBoundingClientRect()读取内容完整尺寸写入heightRef/widthRef渲染时以 CSS 自定义属性的形式暴露--radix-collapsible-content-height与--radix-collapsible-content-width打开时立即渲染以获取尺寸关闭时延迟更新present确保尺寸在收起动画开始前仍可读取用requestAnimationFrame跳过首次挂载动画避免打开时出现闪烁。对应的 Storybook 动画样式 展示了标准用法keyframes collapsible-slideDown { from { height: 0; } to { height: var(--radix-collapsible-content-height); } } keyframes collapsible-slideUp { from { height: var(--radix-collapsible-content-height); } to { height: 0; } } .animatedContent { overflow: hidden; [data-stateopen] { animation: collapsible-slideDown 300ms ease-out; } [data-stateclosed] { animation: collapsible-slideUp 300ms ease-in; } }水平展开同样支持使用--radix-collapsible-content-width即可。挂载/卸载的时机由 Presence 组件接管它基于animationstart/animationend/animationcancel事件驱动一个mounted → unmountSuspended → unmounted状态机确保退出动画完整播放后才从 DOM 移除节点若内容没有动画animationName none则会立即卸载。CollapsibleContent还提供forceMount属性让使用者如接入 React 动画库时完全接管挂载时机。事件合并与 asChildPrimitive 设计的两处细节与 Radix 其它组件一致Collapsible 组件在 Root/Trigger/Content 的测试 中验证了两个通用能力事件合并而非覆盖Trigger 的onClick通过composeEventHandlers来自radix-ui/primitive与内部开合逻辑合并因此外部onClick依然会被调用测试第 238-240 行注释明确说明 Composed with the triggers own click handler rather than replaced by it。asChild 属性透传启用asChild后组件自身的className、style、ref、data-state等全部转发到子元素如将 Trigger 渲染为自定义button或将 Content 渲染为article而 Root 的data-state也会正确落到子节点上。依赖治理与 RSC 兼容1.1.20 的关键决策1.1.20 是该组件的当前版本其核心变更只有一句回退了会导致 React Server Components 兼容性问题的破坏性变更Reverted breaking changes that caused compatibility issues with React Server Components。从源码可见index.ts 以use client声明客户端边界这保证了包可安全地在 RSC 环境如 Next.js App Router中引用。1.1.18 则通过 CI 重新发布所有包以附加 provenance来源证明认证——此前手动发布未包含该证明属于供应链安全治理的补齐。从 package.json 可以看到该组件共依赖 8 个内部子包primitive、react-compose-refs、react-context、react-id、react-presence、react-primitive、react-use-controllable-state、react-use-layout-effect。peerDependencies 支持react ^16.8 || ^17.0 || ^18.0 || ^19.0而sideEffects: false声明为 tree-shaking 友好。Tree-shaking 与 ElementRef 迁移1.1.17 / 1.1.11 的构建优化两个版本分别处理了打包体积与类型层面的工程问题1.1.17所有组件部分改用具名渲染函数并标记/* __PURE__ */替换了此前Component.displayName ...的赋值写法。前者让 bundler如 webpack/rollup在未使用该组件时能够将其彻底删除而displayName赋值产生的副作用会阻碍 dead-code elimination。在 collapsible.tsx 源码中每个组件定义处都可看到/* __PURE__ */ React.forwardRef的实际标注。1.1.11将已废弃的ElementRef类型替换为ComponentRefPR #3426消除 React 类型层面的弃用警告组件内部也全面使用React.ComponentRef定义元素类型。完整版本变更时间线速查版本核心变更主要依赖更新1.1.20回退破坏性变更修复 RSC 兼容性presence、primitive、compose-refs、context、id、use-controllable-state、use-layout-effect1.1.19依赖升级primitive2.1.91.1.18通过 CI 重新发布附加 provenance 认证primitive、compose-refs、context、id、presence、primitive 等1.1.17__PURE__标注与具名渲染函数改善 tree-shakingpresence、use-controllable-state、primitive 等1.1.16依赖升级primitive、context、presence1.1.15 / 1.1.14依赖升级primitive1.1.13修复关闭状态aria-controls引用不存在元素补全repository.directorypresence、primitive、compose-refs、context、id、use-controllable-state、use-layout-effect1.1.12依赖升级presence、primitive、context1.1.11ElementRef→ComponentRef#3426primitive1.1.10 / 1.1.9 / 1.1.8依赖升级primitive / presence1.1.7 / 1.1.6依赖升级use-controllable-state1.1.5useControllableState性能改进、减少 bug 面、误用时输出警告#3455use-controllable-state1.2.0、primitive2.1.0从变更日志还可以看出 Radix 的版本治理特点大量版本是纯粹的依赖升级仅更新锁定的内部子包版本号真正的行为变更集中在少数几个版本1.1.13、1.1.17、1.1.18、1.1.20这反映了 monorepo 中内部包以固定版本锁互相引用的治理方式——升级任一子包都会产生一个新的组件 patch 版本。版本升级与工程实践启示升级策略若你的项目使用 Next.js App Router 等 RSC 环境建议优先升级至 1.1.20该版本专门回退了 RSC 兼容性问题使用打包器且在意产物体积的项目可关注 1.1.17 的 tree-shaking 收益。无障碍验证collapsible.test.tsx 中通过vitest-axe执行自动化无障碍检测toHaveNoViolations说明该组件对aria-*属性的一致性是经过测试保障的。源码地图继续深入可依次阅读 组件实现、客户端入口、Presence 动画核心、Storybook 示例 与 SSR 验证页即可完整掌握该组件从 API 到实现的全貌。赞分享前端UI组件【免费下载链接】primitivesRadix Primitives is an open-source UI component library for building high-quality, accessible design systems and web apps. Maintained by workos.项目地址https://gitcode.com/gh_mirrors/pr/primitives点击查看免费下载相关推荐用 go2rtc 流媒体网关接入 UniFi Protect把私有摄像头流转成标准 RTSP 流5 分钟走通用 go2rtc 流媒体网关接入 UniFi Protect把私有摄像头流转成标准 RTSP 流5 分钟走通 读完这篇你能在自己的 Synology NA前端UI组件OpenCore Legacy Patcher 完整上手指南老 Mac 免费装最新 macOSOpenCore Legacy Patcher 完整上手指南老 Mac 免费装最新 macOS 打开系统设置想升级弹窗却写着此 Mac 型号不受支持前端UI组件Zerobyte快速上手自托管加密备份自动化指南Zerobyte快速上手自托管加密备份自动化指南 如果你的数据保护还停留在想起来才手动复制一遍那误删文件或硬盘故障时恢复基本无望。Zerobyte 是后端前端任务调度存储上一篇Blender超级IO插件用复制粘贴彻底改变你的3D工作流下一篇终极指南如何免费解锁Wand专业版功能并突破2小时限制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →