OHIF 3.10 Button 组件迁移指南:从 @ohif/ui 到 @ohif/ui-next 的完整实践

📅 发布时间:2026/9/19 10:32:16
OHIF 3.10 Button 组件迁移指南:从 @ohif/ui 到 @ohif/ui-next 的完整实践
OHIF 3.10 Button 组件迁移指南从 ohif/ui 到 ohif/ui-next 的完整实践【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers本文是 OHIF 3.9 → 3.10 迁移系列中关于Button按钮组件的专项指南。OHIF 3.10 将主 UI 组件库从ohif/ui迁移至全新的ohif/ui-next基于 shadcn/ui 与 Radix UI 风格按钮体系发生了系统性重构ButtonEnums被废弃、样式控制从手写 Tailwind 类转向variant/size属性、IconButton与ButtonGroup被更通用的组合替代。阅读本文后你将掌握新的Button组件 API、语义化颜色体系的使用方式并能将旧版按钮代码完整迁移到 3.10覆盖普通按钮、图标按钮、分组选择器、视图操作按钮与弹窗底部操作条等全部场景。一、为什么 3.10 要重做 Button组件库换代带来的连锁变化OHIF 3.10 的核心 UI 库从ohif/ui切换为ohif/ui-next这不仅是包名的变化更是一次设计体系的重构。按钮相关的变化可以归结为五个关键点变化维度3.9旧3.10新组件来源ohif/ui中的Buttonohif/ui-next中的Button样式控制ButtonEnums.type如primary 手写 Tailwind 类variant属性字符串字面量 少量布局类颜色体系自定义类text-primary-active、bg-primary-main语义化颜色类text-primary、bg-primary、text-muted-foreground图标按钮独立IconButton组件Button variantghost sizeicon 内嵌Icons.ByName按钮分组独立ButtonGroup组件Tabs/TabsList/TabsTrigger组合新的Button组件实现于 Button.tsx它基于class-variance-authoritycva的buttonVariants定义样式变体并支持asChild通过 Radix UISlot将样式透传给子元素与dataCY测试选择器两个扩展属性。从源码可以看到其基础样式已经内置了圆角、行高、焦点环focus-visible:ring-1、禁用态disabled:opacity-50等一致性处理这正是迁移后可以大量删减手写类的原因。二、认识新Buttonvariant与size属性详解新Button的样式完全由variant和size两个属性驱动两者的全部取值及对应的样式语义都定义在 Button.tsx 的buttonVariants中。variant可选值取值样式语义适用场景default实心主色背景bg-primary/85hover 加深页面主要操作、表单提交secondary次级背景bg-secondary/85次重要操作如播放/暂停outline描边按钮border-primary/25需要弱化主色的独立操作ghost无背景透明按钮hover 显示浅色底图标按钮、工具栏轻量操作destructive危险操作红色系删除、清空等破坏性操作link文字链接样式hover 下划线行内文字动作size可选值取值尺寸适用场景defaulth-7 px-2 py-2常规按钮smh-6 rounded px-2紧凑布局、面板内按钮lgh-9 rounded px-2强调型大按钮iconh-6 w-6正方形纯图标按钮未显式指定时默认值为variant: default、size: default。由于 cva 的合并机制className中传入的类会与变体类共存因此迁移时可以只保留必要的布局/定位类间距、宽度、对齐视觉类颜色、hover、尺寸交给variant与size自动处理。三、迁移步骤一更新导入旧代码通常这样导入按钮及其枚举- import { Button, ButtonEnums, IconButton } from ohif/ui; import { Button, Icons } from ohif/ui-next;注意三点变化IconButton不再需要单独导入它被Button Icons.ByName的组合替代ButtonEnums整体废弃不再有ButtonEnums.type.primary、ButtonEnums.size.medium这类枚举引用图标统一通过Icons.ByName动态渲染图标名以字符串传入。ohif/ui-next的 components/index.ts 中统一导出了Button、Icons、Tabs、FooterAction、ViewportActionButton等全部组件可按需按名导入。四、迁移步骤二手写样式收敛为variant与size旧版按钮常见写法是在className中堆叠大量 Tailwind 类控制颜色、hover 态与尺寸。迁移时应删除这些视觉类改用属性驱动仅保留布局类。以动态容积扩展的DynamicVolumeControls.tsx为例旧代码- Button - classNamemt-2 !h-[26px] !w-[115px] self-start !p-0 - onClick{() { onGenerate(computeViewMode); }} - Button variantdefault sizesm classNamemt-2 h-[26px] w-[115px] self-start p-0 // 只保留布局/定位类 onClick{handleGenerate} Generate /Button几点实践提示原代码中的!h-[26px]、!w-[115px]、!p-0使用!前缀强制覆盖组件样式迁移后由sizesm接管高度!前缀不再需要宽度w-[115px]、上边距mt-2、左对齐self-start属于业务布局予以保留事件回调建议像源码中的handleGenerate那样包裹一层函数内部用typeof onGenerate function做防御性校验避免组件卸载或回调缺失时抛错见 DynamicVolumeControls.tsx。五、迁移步骤三IconButton替换为Button Icons.ByName旧版用独立的IconButton组件包裹图标。新写法是Button variantghost sizeicon或按视觉需要选secondary把图标组件作为子元素嵌入并使用语义化颜色类。以动态容积 4D 控制区的播放/暂停按钮为例- IconButton - classNamebg-customblue-30 h-[26px] w-[58px] rounded-[4px] - onClick{() onPlayPauseChange(!isPlaying)} - - Icon - name{getPlayPauseIconName()} - classNameactive:text-primary-light hover:bg-customblue-300 h-[24px] w-[24px] cursor-pointer text-white - / - /IconButton Button idplay-pause-button variantsecondary // 或按最终视觉要求用 ghost sizedefault // 纯图标时用 icon classNamew-[58px] // 必要时保留固定宽度 onClick{() { if (typeof onPlayPauseChange function) { onPlayPauseChange(!isPlaying); } }} Icons.ByName name{getPlayPauseIconName()} classNametext-foreground h-[24px] w-[24px] // 使用语义化颜色 / /Button迁移要点IconButton的外层视觉样式背景、圆角、hover由variant接管无需手写bg-customblue-30 rounded-[4px]图标实例从ohif/ui的Icon换成ohif/ui-next的Icons.ByNamename仍是字符串如icon-play/icon-pause。Icons.ByName的实现见 Icons.tsx它会从内部图标注册表按名查找组件未找到时给出Missing Icon占位提示图标颜色类active:text-primary-light hover:bg-customblue-300 text-white全部替换为语义化类text-foreground避免硬编码自定义调色板。这一迁移在仓库中的真实落地可以直接对照 DynamicVolumeControls.tsxplay-pause-button按钮正是variantsecondarysizedefault 内嵌Icons.ByName的形态与上述 diff 完全一致。六、迁移步骤四ButtonGroup替换为Tabs组合ButtonGroup在 3.10 被废弃。用于「互斥选择一组选项」的场景应改用ohif/ui-next的Tabs、TabsList、TabsTrigger通过value与onValueChange管理选中态。以动态容积 4D/Computed 视图切换为例- ButtonGroup classNamemt-2 w-full - button classNamew-1/2 onClick{() setComputedView(false)}4D/button - button classNamew-1/2 onClick{() setComputedView(true)}Computed/button - /ButtonGroup Tabs value{computedView ? computed : 4d} onValueChange{value setComputedView(value computed)} classNamemy-2 w-full TabsList classNamew-full TabsTrigger value4d classNamew-1/24D/TabsTrigger TabsTrigger valuecomputed classNamew-1/2Computed/TabsTrigger /TabsList /Tabs仓库中的实际实现 Tabs.tsx 基于 Radix UI 的TabsPrimitive封装TabsList提供分组容器样式bg-primary/20底、圆角TabsTrigger通过data-[stateactive]属性自动切换选中态样式选中项自动获得高亮底与阴影无需手写 active 类Tabs的value必须是受控的字符串与onValueChange配套使用。动态容积扩展中视图切换4D/Computed与计算操作符SUM/AVERAGE/SUBTRACT两个分组都已迁移为 Tabs 形态见 DynamicVolumeControls.tsx 与 DynamicVolumeControls.tsx。七、迁移步骤五识别领域专用组件替换并非所有按钮都该用通用Button。3.10 提供了若干领域专用组件迁移时优先识别并替换代码更语义化7.1 视口操作按钮ViewportActionButton旧代码常用「带 hover 效果的可点击div」充当视图操作按钮如 SR/SEG/RT 数据的加载按钮。3.10 用ViewportActionButton替代它接收onInteraction回调、可选id与commands内部通过onMouseUp触发交互源码注释说明使用onMouseUp是因为在pointer-events: none场景下onClick可能不触发样式基于语义化bg-primary/60 hover:bg-primary/80见 ViewportActionButton.tsx。- div - classNamebg-primary-main hover:bg-primary-light ml-1 cursor-pointer rounded px-1.5 hover:text-black - onMouseUp{onStatusClick} - - {loadStr} - /div ViewportActionButton onInteraction{onStatusClick}{loadStr}/ViewportActionButton该组件在 cornerstone 扩展的ModalityLoadBadge中已有落地当视口加载了未水合hydration的 SR/SEG/RTSTRUCT 显示集时会渲染一个ViewportActionButton点击后通过commandsManager.runCommand(hydrateSecondaryDisplaySet, ...)触发水合见 ModalityLoadBadge.tsx。7.2 弹窗底部操作条FooterAction弹窗/对话框底部的「确定 / 取消」操作旧版常直接使用带枚举属性的Button。3.10 推荐用复合组件FooterAction它由Left/Right容器与Primary/Secondary/Auxiliary三个动作子组件组成见 FooterAction.tsxFooterAction根组件根据是否包含Left/Right自动决定 flex 布局的对齐方式justify-between/justify-start/justify-endFooterAction.Primary对应variantdefault实心主按钮默认min-w-[80px]FooterAction.Secondary对应variantsecondary次级按钮FooterAction.Auxiliary对应variantghost弱化操作。以容积渲染预设对话框的取消按钮为例- Button - nameCancel - size{ButtonEnums.size.medium} - type{ButtonEnums.type.secondary} - onClick{onClose} - Cancel /Button FooterAction FooterAction.Right FooterAction.Secondary onClick{hide}Cancel/FooterAction.Secondary /FooterAction.Right /FooterAction仓库中的完整落地见 VolumeRenderingPresetsContent.tsx该文件同时展示了Icons.ByName在预置项网格中的使用可一并参考。八、迁移步骤六颜色体系升级拥抱语义化令牌3.10 用语义化颜色令牌替代了旧的自定义调色板类。迁移时按下表对应替换旧自定义类示例新语义化类text-primary-active、text-primary-lighttext-primary/text-foregroundbg-primary-main、bg-primary-light、bg-customblue-30bg-primary/bg-secondaryhover 态由variant接管hover:text-black、active:text-primary-lighthover/active 颜色状态由variant自动处理text-muted等text-muted-foreground语义化类的核心收益在于颜色状态hover、active由variant自动管理开发者不再需要为每个按钮手工编写交互态样式同时主题切换浅色/深色时令牌会自动适配消除了硬编码色值带来的不一致。FooterAction、ViewportActionButton、Tabs等组件内部均已使用这套令牌体系业务代码沿用即可。九、迁移清单与自检完成按钮迁移后可按以下清单逐项自检导入检查所有ohif/ui的Button/IconButton/ButtonEnums/ButtonGroup引用已清除统一改为ohif/ui-next的Button、Icons、Tabs、FooterAction、ViewportActionButton样式检查按钮 className 中不再出现!h-、!w-强制类与bg-customblue-*、text-primary-active等自定义色值视觉样式由variant/size接管仅保留布局/定位类交互检查IconButton均已替换为Button Icons.ByName图标名称仍是字符串ButtonGroup均已替换为受控Tabsvalue/onValueChange配对正确领域组件检查可点击的div型操作按钮已替换为ViewportActionButton弹窗底部操作已替换为FooterAction的Left/Right/Primary/Secondary/Auxiliary组合回归验证hover、active、disabled 等交互态样式正常按钮在pointer-events受限场景如 3D 视口叠加层仍可点击禁用态视觉disabled:opacity-50符合预期。十、参考文件索引新Button组件及variant/size定义Button.tsx新Tabs组合组件Tabs.tsx图标动态渲染Icons.ByNameIcons.tsx视口操作按钮ViewportActionButton.tsx弹窗底部操作条FooterAction.tsx按钮迁移真实落地示例DynamicVolumeControls.tsxTabs 分组、播放按钮、Generate 按钮、VolumeRenderingPresetsContent.tsxFooterAction 取消、ModalityLoadBadge.tsxViewportActionButton 水合触发【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考