
Coolify 前端组件指南shadcn/ui 中 base 与 radix 两套原语库的 API 差异详解【免费下载链接】coolifyAn open-source, self-hostable PaaS alternative to Vercel, Heroku Netlify that lets you easily deploy static sites, databases, full-stack applications and 280 one-click services on your own servers.项目地址: https://gitcode.com/GitHub_Trending/co/coolifyCoolify 仓库在.agents/skills/shadcn/rules/base-vs-radix.md中维护了一份针对 AI/开发协作的规则文档专门记录 shadcn/ui 项目使用base原语库Base UI与radix原语库Radix UI时组件 API 的系统性差异。本文完整继承并展开该文档的全部规则从组合模式asChildvsrender、nativeButton修正到 Select、ToggleGroup、Slider、Accordion 四大组件的逐项 API 对照帮助你在新建或维护 shadcn/ui 项目时先确认项目所属原语库再写出符合该库语义的正确组件代码。1. 先判断项目属于哪套原语库base字段两套 API 的差异是同组件、不同签名级别的问题同一份代码直接照搬另一套库会编译报错或行为异常因此第一步永远是确认当前项目的原语库。规则文档的第一句话即给出了方法检查npx shadcnlatest info输出中的base字段。配套的 CLI 参考文档cli.md对info命令做了更完整的说明info命令读取项目根目录的components.json输出项目信息与配置字段components.json字段表中的base字段被明确定义为原语库radix或base决定组件 API 与可用 props其他相关字段还包括style视觉风格、iconLibrary图标库、tailwindVersionv3/v4、resolvedPaths各别名的绝对文件系统路径等。npx shadcnlatest info技能主文件 SKILL.md 在Component Structure规则中直接引用了本文档作为强制规则使用asChildradix或renderbase做自定义 trigger通过npx shadcnlatest info检查base字段。此外docs命令的输出也会以base radix的列头展示各组件在不同原语库下的文档与示例位置这从侧面印证了 shadcn/ui 官方对两套库分别维护文档的机制。2. 组合模式asChildradixvsrenderbase这是两套库最基础、出现频率最高的差异Radix 用asChild属性来替换默认渲染的元素Base 用render属性传入元素。通用原则是不要把 trigger 再包一层多余的元素。错误写法两套库均适用——trigger 内嵌套了多余divDialogTrigger div ButtonOpen/Button /div /DialogTrigger正确写法radixDialogTrigger asChild ButtonOpen/Button /DialogTrigger正确写法baseDialogTrigger render{Button /}Open/DialogTrigger注意两者的语义差别radix 的asChild让 trigger 把属性合并进唯一子元素base 的render则是直接接收一个 React 元素作为渲染目标文本作为 children 传入。这一条规则适用于文档列出的全部 trigger/close 类组件DialogTrigger、SheetTrigger、AlertDialogTrigger、DropdownMenuTrigger、PopoverTrigger、TooltipTrigger、CollapsibleTrigger、DialogClose、SheetClose、NavigationMenuLink、BreadcrumbLink、SidebarMenuButton、Badge、Item。3. 把 Button / trigger 渲染成非按钮元素base 专属陷阱当render把一个元素改成非按钮元素如a、span时base 库必须额外加上nativeButton{false}否则底层仍按原生button处理导致出现button包裹a这类无效嵌套。错误写法base——缺少nativeButton{false}Button render{a href/docs /}Read the docs/Button正确写法baseButton render{a href/docs /} nativeButton{false} Read the docs /Button正确写法radix——等价场景用asChild无此属性Button asChild a href/docsRead the docs/a /Button同样的规则适用于render目标不是Button的 trigger例如把 Popover 的 trigger 渲染成输入组的附加元素// base. PopoverTrigger render{InputGroupAddon /} nativeButton{false} Pick date /PopoverTrigger4. Selectitemsprop、占位符与内容定位4.1itemspropbase 专属Base 要求根组件传入items数组作为数据源Radix 只使用内联 JSX没有这个概念。错误写法base——漏传itemsSelect SelectTriggerSelectValue placeholderSelect a fruit //SelectTrigger /Select正确写法baseconst items [ { label: Select a fruit, value: null }, { label: Apple, value: apple }, { label: Banana, value: banana }, ] Select items{items} SelectTrigger SelectValue / /SelectTrigger SelectContent SelectGroup {items.map((item) ( SelectItem key{item.value} value{item.value}{item.label}/SelectItem ))} /SelectGroup /SelectContent /Select正确写法radix——内联声明选项Select SelectTrigger SelectValue placeholderSelect a fruit / /SelectTrigger SelectContent SelectGroup SelectItem valueappleApple/SelectItem SelectItem valuebananaBanana/SelectItem /SelectGroup /SelectContent /Select注意两个写法的共同点SelectItem必须位于SelectGroup之内。这是仓库中另一条强制规则——Items 必须放在各自的 Group 内见 composition.mdSelectItem→SelectGroup是其列举的第一行与本文档互相印证。4.2 占位符Placeholder的实现方式不同base占位符是items数组中value: null的那一项如上面的{ label: Select a fruit, value: null }radix使用SelectValue placeholder...属性表达。4.3 下拉内容的定位属性base用alignItemWithTriggerradix用position。// base. SelectContent alignItemWithTrigger{false} sidebottom // radix. SelectContent positionpopper5. Select多选与对象值base 专属能力文档明确指出Base 支持multiple、SelectValue的 render-function children、以及通过itemToStringValue处理对象值而Radix 的 Select 是单选、且仅支持字符串值。也就是说多选与对象值场景在 base 库是一等公民在 radix 库需要换组件或自行封装。base 多选示例Select items{items} multiple defaultValue{[]} SelectTrigger SelectValue {(value: string[]) value.length 0 ? Select fruits : ${value.length} selected} /SelectValue /SelectTrigger ... /Select这里SelectValue的 children 是一个函数参数为当前选中的值数组可在其中渲染任意摘要文本如已选 N 项。base 对象值示例选中项是对象时用itemToStringValue提取字符串身份用 render function 展示展示字段Select defaultValue{plans[0]} itemToStringValue{(plan) plan.name} SelectTrigger SelectValue{(value) value.name}/SelectValue /SelectTrigger ... /Select6. ToggleGrouptypevsmultipleBase 使用multiple布尔属性表达多选Radix 使用typesingle或typemultiple枚举属性。更隐蔽的差异在于defaultValue的类型base 的defaultValue始终是数组radix 的单选defaultValue是字符串。错误写法base——误用了 radix 的typesingle与字符串默认值ToggleGroup typesingle defaultValuedaily ToggleGroupItem valuedailyDaily/ToggleGroupItem /ToggleGroup正确写法base// 单选不需要任何 propdefaultValue 始终是数组。 ToggleGroup defaultValue{[daily]} spacing{2} ToggleGroupItem valuedailyDaily/ToggleGroupItem ToggleGroupItem valueweeklyWeekly/ToggleGroupItem /ToggleGroup // 多选。 ToggleGroup multiple ToggleGroupItem valueboldBold/ToggleGroupItem ToggleGroupItem valueitalicItalic/ToggleGroupItem /ToggleGroup正确写法radix// 单选defaultValue 是字符串。 ToggleGroup typesingle defaultValuedaily spacing{2} ToggleGroupItem valuedailyDaily/ToggleGroupItem ToggleGroupItem valueweeklyWeekly/ToggleGroupItem /ToggleGroup // 多选。 ToggleGroup typemultiple ToggleGroupItem valueboldBold/ToggleGroupItem ToggleGroupItem valueitalicItalic/ToggleGroupItem /ToggleGroup受控单选值的差异——base 需要在状态与回调之间手动包裹/解包数组// base —— 数组的 wrap/unwrap。 const [value, setValue] React.useState(normal) ToggleGroup value{[value]} onValueChange{(v) setValue(v[0])} // radix —— 直接是普通字符串。 const [value, setValue] React.useState(normal) ToggleGroup typesingle value{value} onValueChange{setValue}这一条是迁移代码时最容易遗漏的坑状态值在 base 中是string[]在 radix 中是string回调签名随之不同。7. Slider标量 vs 数组Base 的单滑块接受普通数字Radix 的defaultValue一律是数组。错误写法base——把 radix 的数组习惯带过来Slider defaultValue{[50]} max{100} step{1} /正确写法baseSlider defaultValue{50} max{100} step{1} /正确写法radixSlider defaultValue{[50]} max{100} step{1} /两套库在 range双滑块场景都使用数组。但 base 的受控onValueChange回调可能需要一次类型断言// base. const [value, setValue] React.useState([0.3, 0.7]) Slider value{value} onValueChange{(v) setValue(v as number[])} / // radix. const [value, setValue] React.useState([0.3, 0.7]) Slider value{value} onValueChange{setValue} /8. Accordiontype/collapsiblevsmultipleRadix 要求typesingle或typemultiple并支持collapsibledefaultValue是字符串。Base 没有typeprop用multiple布尔值表达多选且defaultValue始终是数组。错误写法base——照搬 radix 的typesingle collapsible与字符串默认值Accordion typesingle collapsible defaultValueitem-1 AccordionItem valueitem-1.../AccordionItem /Accordion正确写法baseAccordion defaultValue{[item-1]} AccordionItem valueitem-1.../AccordionItem /Accordion // 多选。 Accordion multiple defaultValue{[item-1, item-2]} AccordionItem valueitem-1.../AccordionItem AccordionItem valueitem-2.../AccordionItem /Accordion正确写法radixAccordion typesingle collapsible defaultValueitem-1 AccordionItem valueitem-1.../AccordionItem /Accordion9. 差异速查表主题baseBase UIradixRadix UI组合/自定义元素render{Button /}asChild 子元素非按钮渲染a/span需加nativeButton{false}无此概念直接asChildSelect 数据源根组件必须传itemsprop内联 JSX 选项Select 占位符items中value: null项SelectValue placeholder... /Select 定位alignItemWithTriggerpositionpopperSelect 多选/对象值支持multiple、render-functionSelectValue、itemToStringValue单选、仅字符串值ToggleGroup 模式无 prop 单选multiple布尔typesingle/typemultipleToggleGroup 默认值始终是数组单选为字符串Slider 单滑块defaultValue{50}标量defaultValue{[50]}数组Slider 受控回调可能需要as number[]断言直接可用Accordion 模式无typemultiple布尔 数组默认值typesingle/multiplecollapsible 字符串默认值10. 与仓库内其他规则文档的关系本文档并非孤立存在它是 shadcn 技能包中一组强制规则的成员全部规则文件位于.agents/skills/shadcn/rules/目录base-vs-radix.md本文主题——asChildvsrender、Select、ToggleGroup、Slider、Accordion 的 API 差异composition.md——Group/Item 结构、overlay 组件选择、Card/Tabs/Avatar 等组合规则forms.md——FieldGroup/Field、InputGroup、ToggleGroup 在表单中的用法styling.md——语义色、gap-*、size-*、cn()等样式规则icons.md——data-icon与图标尺寸规则。技能主文件 SKILL.md 把上述文件列为always enforced的 Critical Rules其中与本文直接挂钩的强制条目是UseasChild(radix) orrender(base) for custom triggers. Checkbasefield fromnpx shadcnlatest info。此外 SKILL.md 还提到预设preset代码并不编码 base 信息CLI 会自动从components.json保留当前项目的 base若必须在临时目录做--dry-run对比需显式传--base current-base。从这套文档的组织方式可以推断base字段是整个 shadcn/ui 工程约定中决定组件签名的开关本文覆盖的所有差异都应以它为前提先做判定再进入具体组件的 API 选择。【免费下载链接】coolifyAn open-source, self-hostable PaaS alternative to Vercel, Heroku Netlify that lets you easily deploy static sites, databases, full-stack applications and 280 one-click services on your own servers.项目地址: https://gitcode.com/GitHub_Trending/co/coolify创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考