coss Accordion 组件实战指南:从安装、受控展开到 Radix 迁移
2026/9/16 20:55:36 网站建设 项目流程

coss Accordion 组件实战指南:从安装、受控展开到 Radix 迁移

【免费下载链接】app🎯 All you need. Nothing you don't. Open source project management that works for you, not against you.项目地址: https://gitcode.com/GitHub_Trending/app116/app

本指南以开源仓库 coss skill 参考文档 为核心,系统讲解 coss 组件体系中 Accordion(手风琴/可展开多区块内容区)的安装方式、规范导入、最小实现、多面板展开与受控模式,并结合本仓库中真实的 site 端实现 与 web 端实现 深入剖析其底层原理与常见陷阱。读完本文,你将掌握如何在 React + Tailwind CSS v4 + Base UI 项目中正确搭建、定制和迁移 coss Accordion,并规避从 Radix/shadcn 迁移时最容易踩的坑。

何时使用 coss Accordion

Accordion 用于组织可展开的多区块内容区域,是渐进式披露(progressive disclosure)的典型载体。根据原文档(accordion.md),它适合两类典型场景:

  • 可展开的多区块内容:例如长文档的分节导航、配置面板中按类别收纳的设置项;
  • FAQ 与设置页:需要把大量问答或选项压缩进有限空间,用户按需展开查看。

与之相对,若只需要一个独立的"展开/收起"区域(无多条目联动),应优先考虑 collapsible 原语;若需要多标签页互斥切换面板,则应选用 tabs 原语。组件选型可对照 component-registry.md 中的索引快速决策。

安装:CLI 一键添加与手动依赖

方式一:shadcn CLI 添加(推荐)

在项目根目录(需已配置 shadcn 与 Tailwind CSS v4)执行:

npx shadcn@latest add @coss/accordion

根据 coss CLI 参考,项目使用 pnpm 或 bun 时应始终使用对应的包运行器,避免全局二进制版本漂移:

pnpm dlx shadcn@latest add @coss/accordion bunx --bun shadcn@latest add @coss/accordion

建议在正式写入前使用预览模式确认改动范围(组件可能已存在于本地,或你只想先检查将要生成的文件):

npx shadcn@latest add @coss/accordion --dry-run npx shadcn@latest add @coss/accordion --diff npx shadcn@latest add @coss/accordion --view

方式二:手动安装依赖

CLI 之外的"手动安装"路径,核心是按组件文档安装其声明的最小依赖。Accordion 的运行时依赖是 Base UI 的 React 包:

npm install @base-ui/react

安装完成后,将本仓库 apps/site/components/ui/accordion.tsx(或 web 端 apps/web/src/components/ui/accordion.tsx)中导出的四个组件复制到你自己项目的components/ui/accordion.tsx,并把@/lib/cn等导入别名替换为项目实际的别名配置。

手动安装注意事项(见 cli.md):CLI 方式会自动接线所需的主题 token;手动方式若涉及destructive-foregroundinfosuccesswarning等颜色家族,需要自行从 coss 样式文档补齐对应 token。

规范导入

无论哪种安装方式,组件文件最终都从项目的 ui 目录导出以下四个成员:

import { Accordion, AccordionItem, AccordionPanel, AccordionTrigger, } from "@/components/ui/accordion"

对照仓库源码 apps/site/components/ui/accordion.tsx 可以看到导出集合与文档完全一致:Accordion(根)、AccordionItem(条目)、AccordionTrigger(触发器)、AccordionPanel(内容面板),并且额外以别名AccordionContent导出AccordionPanel,兼容 Radix 时代的命名习惯。

最小模式:一个可展开的条目

<Accordion defaultValue={["item-1"]}> <AccordionItem value="item-1"> <AccordionTrigger>What is Base UI?</AccordionTrigger> <AccordionPanel> Base UI is a library of high-quality unstyled React components. </AccordionPanel> </AccordionItem> </Accordion>

要点拆解:

  • Accordion接收字符串数组形式的defaultValue,这与 Base UI 的受控模型一致——即便只有一个面板,也要写成数组["item-1"]
  • 每个AccordionItem必须有稳定且唯一value,它是条目身份标识,也是受控行为的依据;
  • AccordionTriggerAccordionPanel必须是同一个AccordionItem的直接子级,不能跨条目混放。

源码实现印证

从仓库组件实现(apps/site/components/ui/accordion.tsx)可以看到Accordion直接透传AccordionPrimitive.Root的全部 props,并挂上data-slot="accordion"供 Tailwind v4 样式选择器定位;AccordionTrigger内部用AccordionPrimitive.Header包裹真实按钮,并附带一个旋转指示器ChevronDownIcon(见 第 28-42 行);AccordionPanel则通过--accordion-panel-height变量与transition-[height]实现展开/收起的高度动画(见 第 47-61 行)。这意味着你使用四个组件时,开箱即获得无障碍语义(Header + 按钮结构)、键盘焦点环与平滑动画,无需自行实现。

进阶模式:多开、受控与数据映射

多面板同时展开

默认(不传multiple)时 Accordion 为单开模式,展开新面板会收起旧面板。若需要多个面板同时保持展开,显式传入multiple并给出多个默认值:

<Accordion multiple defaultValue={["item-1", "item-2"]}> <AccordionItem value="item-1"> <AccordionTrigger>Section 1</AccordionTrigger> <AccordionPanel>Content 1</AccordionPanel> </AccordionItem> <AccordionItem value="item-2"> <AccordionTrigger>Section 2</AccordionTrigger> <AccordionPanel>Content 2</AccordionPanel> </AccordionItem> </Accordion>

受控模式:外部状态驱动

当需要由外部逻辑(如"全部展开"按钮、URL 参数同步、搜索高亮定位)驱动面板状态时,使用value+onValueChange完全受控:

const [value, setValue] = useState<string[]>(["item-1"]) <Accordion value={value} onValueChange={setValue}> {/* items... */} </Accordion>

再次强调:受控value永远是string[],而不是单个字符串或布尔值。这一约定与 Base UI 的 Accordion API 完全一致,也是从 Radix 迁移时最常见的认知断层。

数据映射(mapped items)模式

配合value数组,最常见的生产形态是遍历数据源批量渲染条目:

const faqs = [ { id: "q1", question: "How does coss work?", answer: "..." }, { id: "q2", question: "Is it accessible?", answer: "..." }, ]; <Accordion multiple defaultValue={faqs.map((f) => f.id)}> {faqs.map((f) => ( <AccordionItem key={f.id} value={f.id}> <AccordionTrigger>{f.question}</AccordionTrigger> <AccordionPanel>{f.answer}</AccordionPanel> </AccordionItem> ))} </Accordion>

该模式对应粒子示例p-accordion-1(mapped items)、p-accordion-2(单开静态区块)、p-accordion-3(多开行为)、p-accordion-4(受控 value + 外部动作),完整列表见 accordion.md。

从 Radix / shadcn 迁移:模型差异对照

coss 的 Accordion 与 Radix 版本在 API 表面上高度相似,但状态模型不同。根据 migration.md 中的对照模板:

// shadcn/Radix:type="single" + collapsible + 字符串 defaultValue <Accordion type="single" collapsible defaultValue="item-1"> <AccordionItem value="item-1">...</AccordionItem> </Accordion> // coss/Base UI:multiple 布尔值 + 数组 defaultValue <Accordion defaultValue={["item-1"]}> <AccordionItem value="item-1">...</AccordionItem> </Accordion>

迁移时只需记住三个等价替换:

Radix 心智模型coss / Base UI 模型
type="single"/type="multiple"布尔属性multiple(缺省即 single)
defaultValue="item-1"(字符串)defaultValue={["item-1"]}(字符串数组)
受控value为标量受控value恒为string[]

此外,coss 迁移规则(migration.md)强调:不要假设所有 shadcn 模式都能 1:1 平移;对触发器类组件要逐原语核对文档中的 trigger/content 层级;asChild仅在明确支持render的部件上替换为render

常见陷阱清单

原文档(accordion.md)归纳了四个高频错误,全部可在仓库实现中找到对应约束:

  1. AccordionTrigger/AccordionPanel放在AccordionItem之外——破坏条目的子级结构,导致状态无法归属到对应条目(实现见 apps/site/components/ui/accordion.tsx);
  2. AccordionItem上省略value——条目失去身份标识,展开状态无法追踪,受控模式直接失效;
  3. 套用 Radix 的type="single" | "multiple"心智——coss 用布尔multiple+ 数组值,混用会产生类型错误或行为异常;
  4. 把受控value当成标量——必须使用string[],否则受控行为不成立。

自检清单

在提交 coss Accordion 代码前,对照 SKILL.md 的输出清单逐项确认:

  • 导入路径与导出成员与组件文档一致(Accordion/AccordionItem/AccordionPanel/AccordionTrigger);
  • 每个AccordionItem都有稳定唯一的valueTriggerPanel是同一 item 的子级;
  • 受控用法使用string[]类型的value+onValueChange
  • 无障碍结构完整:AccordionTrigger内含Header,可键盘操作,焦点环样式保留;
  • 迁移代码已用迁移规则核对(migration.md),未保留type等 Radix 专属 props。

按此清单核对后,coss Accordion 即可安全落地到 FAQ、设置页等渐进式披露场景,并获得与仓库 site / web 实现一致的体验质量。

【免费下载链接】app🎯 All you need. Nothing you don't. Open source project management that works for you, not against you.项目地址: https://gitcode.com/GitHub_Trending/app116/app

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询