Ant Design Collapse 组件完全指南:可折叠内容面板的 API、语义化定制与 Design Token 深度解析
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design
Collapse 是 ant-design(企业级 React UI 组件库)中用于"分组与收纳复杂内容区域"的数据展示组件:用户点击面板头部即可展开或收起内容区,同时支持一次只展开一栏的手风琴(Accordion)模式。本文以仓库中的官方英文文档 components/collapse/index.en-US.md 为主体,结合 Collapse.tsx、CollapsePanel.tsx、style/index.ts 与全部官方 demo 源码,系统讲解 Collapse 的适用场景、每个 API 的含义与默认值、items 声明式配置法、Semantic DOM 语义化定制以及 Design Token 主题令牌体系,并附带可复制的完整代码示例。
When To Use:什么场景该用 Collapse
官方文档给出了两条核心适用判断:
- 分组或隐藏复杂区域,让页面保持整洁(例如设置中心把"基础设置 / 安全设置 / 通知设置"收进可展开区块);
- Accordion(手风琴)模式:它是 Collapse 的一种特殊形态,同一时刻只允许展开一个面板。
换句话说,Collapse 解决的是一类典型的"信息分层"问题——把高频可见的标题(header)留在页面上,把低频访问的细节(body)收纳起来按需展开,避免长页面一次性渲染过多信息。
基础用法与受控/非受控状态
Collapse 支持两种状态管理方式:
- 非受控:通过
defaultActiveKey指定初始展开面板,用户交互由组件内部维护; - 受控:通过
activeKey+onChange完全由业务代码控制当前展开项。
下面是最基础的用法(改写自 demo/basic.tsx):
import { Collapse } from 'antd'; import type { CollapseProps } from 'antd'; const text = ` A dog is a type of domesticated animal. Known for its loyalty and faithfulness, it can be found as a welcome guest in many households across the world. `; const items: CollapseProps['items'] = [ { key: '1', label: 'This is panel header 1', children: <p>{text}</p>, }, { key: '2', label: 'This is panel header 2', children: <p>{text}</p>, }, { key: '3', label: 'This is panel header 3', children: <p>{text}</p>, }, ]; const App: React.FC = () => { const onChange = (key: string | string[]) => { console.log(key); }; return <Collapse items={items} defaultActiveKey={['1']} onChange={onChange} />; }; export default App;注意onChange的回调参数类型:在 Collapse.tsx 中定义为(key: string[]) => void,演示代码里同时兼容了string | string[]的写法。从源码结构看,多选场景下返回的是当前所有展开面板 key 组成的数组。
若需完全受控,把defaultActiveKey={['1']}换成activeKey={...},并在onChange里更新状态即可。展开动画由组件内部配置:在 Collapse.tsx 中可以看到,openMotion复用了initCollapseMotion(项目自带的展开折叠运动曲线),并关闭了出现动画(motionAppear: false),展开完成后残留类名被置为${prefixCls}-panel-hidden以彻底隐藏内容。
Accordion 手风琴:一次只展开一栏
手风琴模式只需加一个accordion布尔属性(见 demo/accordion.tsx):
import { Collapse } from 'antd'; import type { CollapseProps } from 'antd'; // items 定义同上:key 为 '1' / '2' / '3' 的三个面板 const App: React.FC = () => <Collapse accordion items={items} />; export default App;手风琴模式下,activeKey/defaultActiveKey通常传单个字符串或数字(例如defaultActiveKey="1")。官方 API 表对activeKey的描述是:默认为空、在 accordion 模式中默认展开第一个面板的 key。
API 全解析:Collapse 组件属性
官方文档给出如下属性表,其中Global Config列表示该属性是否可被 ConfigProvider 的 componentConfig 全局统一下发:
| Property | Description | Type | Default | Version | Global Config |
|---|---|---|---|---|---|
| accordion | If true, Collapse renders as Accordion | boolean | false | × | |
| activeKey | Key of the active panel | string[] | string / number[] | number | No default value. In accordion mode, it's the key of the first panel | × | |
| bordered | Toggles rendering of the border around the collapse block | boolean | true | × | |
| classNames | Customize class for each semantic structure inside the component. Supports object or function. | Record<SemanticDOM, string>|(info: { props }) => Record<SemanticDOM, string> | - | 6.0.0 | 支持 |
| collapsible | Specify how to trigger Collapse. Either by clicking icon or by clicking any area in header or disable collapse functionality itself | header|icon|disabled | - | 4.9.0 | × |
| defaultActiveKey | Key of the initial active panel | string[] | string / number[] | number | - | × | |
| Destroy Inactive Panel (已废弃) | boolean | false | × | ||
| destroyOnHidden | Destroy Inactive Panel(卸载隐藏面板内容) | boolean | false | 5.25.0 | × |
| expandIcon | Customize the collapse expand icon | (panelProps) => ReactNode | - | 5.15.0(支持全局) | |
| expandIconPlacement | Set expand icon placement | start|end | start | × | |
Set expand icon position,请改用expandIconPlacement | start|end | - | 4.21.0 | × | |
| ghost | Make the collapse borderless and its background transparent | boolean | false | 4.4.0 | × |
| size | Set the size of collapse | large|medium|small | medium | 5.2.0 | × |
| styles | Customize inline style for each semantic structure. Supports object or function. | Record<SemanticDOM, CSSProperties>|(info: { props }) => Record<SemanticDOM, CSSProperties> | - | 6.0.0(支持全局) | |
| onChange | Callback function executed when active panel is changed | function | - | × | |
| items | collapse items content | ItemType | - | 5.6.0 | × |
源码级核对与关键属性的补充解读
对照 Collapse.tsx 的实现,可以确认以下几点:
- bordered / ghost 类名机制:
bordered={false}会附加${prefixCls}-borderless类;ghost会附加${prefixCls}-ghost类,视觉差异完全由 style/index.ts 中的genBorderlessStyle与genGhostStyle驱动。ghost 模式下面板无边框、背景透明,适合浅色页面顶部等需要弱化容器视觉的场景。 - size 的默认值与继承链:
size的类型源自 ConfigProvider 的SizeType,组件通过useSize合并「自身 prop → ConfigProvider 全局 size → 默认 'middle'」三层取值(Collapse.tsx)。因此文档表格中的默认值medium与代码中的回退值'middle'语义一致:仅在无任何全局配置时生效。 - expandIconPosition 已废弃:代码中使用
mergedPlacement = expandIconPlacement ?? expandIconPosition ?? 'start'做向后兼容,同时在非生产环境下通过devUseWarning打出 deprecated 警告(Collapse.tsx),提示改用expandIconPlacement。 - destroyInactivePanel 已废弃:同理被
destroyOnHidden取代,兼容逻辑为destroyOnHidden ?? destroyInactivePanel(Collapse.tsx)。语义上destroyOnHidden强调"面板被隐藏时销毁其 DOM 子树",适合内容重、需要释放内存或重置内部状态的场景,代价是每次展开都会重新渲染内容节点(与forceRender配合时需按需选择)。 - RTL 支持:当 ConfigProvider 的
direction="rtl"时,根节点会加上${prefixCls}-rtl类(Collapse.tsx),展开箭头旋转方向也随之翻转(style/index.ts)。 - 展开/收起箭头动画:箭头使用
RightOutlined图标,展开时旋转 90°(RTL 下为 -90°),旋转过渡时长取自motionDurationSlow。若箭头本身可作为点击热区(collapsible="icon"或"header"),会为图标附加aria-label="expanded"/"collapsed";否则标为aria-hidden,保证可访问性(Collapse.tsx)。
三种尺寸(size)
仓库 demo/size.tsx 展示了small/medium(缺省)/large三种尺寸,分别通过${prefixCls}-small与${prefixCls}-large类切换内边距与字号。从样式源码(style/index.ts)可以看到三种尺寸影响 header 与 body 的padding以及大号尺寸的fontSize(取fontSizeLG)。
面板折叠触发区域(collapsible)
collapsible决定"点哪里才能折叠",取值header、icon、disabled(见 demo/collapsible.tsx):
<Collapse collapsible="header" defaultActiveKey={['1']} items={items} /> <Collapse collapsible="icon" defaultActiveKey={['1']} items={items} /> <Collapse collapsible="disabled" items={items} />"header":点击标题文字或图标都可折叠/展开;"icon":只有点击箭头图标时才可折叠,适合标题本身还承载其他交互(比如标题内含链接或复选框)的场景;"disabled":完全禁用折叠交互,头部呈现禁用色与not-allowed光标。对应样式位于 style/index.ts,其中-collapsible-header/-collapsible-icon分别把cursor: pointer限制在标题或图标局部。
从 v4.9.0 起该属性也可配置在单个面板上(见下文 ItemType 与 Collapse.Panel)。面板级disabled写法已废弃,源码会在非生产环境提示改用collapsible="disabled"(CollapsePanel.tsx)。
ItemType:推荐的面板声明式配置(v5.6.0+)
自 5.6.0 起官方推荐用items数组声明面板内容。ItemType 属性表如下:
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| classNames | Semantic structure className | Record<header \| body, string> | - | 5.21.0 |
| collapsible | Specify whether the panel be collapsible or the trigger area | header|icon|disabled | - | |
| children | Body area content | ReactNode | - | |
| extra | The extra element in the corner | ReactNode | - | |
| forceRender | Forced render of content on panel, instead of lazy rendering after clicking on header | boolean | false | |
| key | Unique key identifying the panel from among its siblings | string | number | - | |
| label | Title of the panel | ReactNode | - | - |
| showArrow | If false, panel will not show arrow icon. 若为 false,则 collapsible 不能设为icon | boolean | true | |
| styles | Semantic DOM style | Record<header \| body, CSSProperties> | - | 5.21.0 |
extra:面板右上角的附加节点
extra用于在面板角落追加操作节点(如"编辑"按钮、状态标签等),见 demo/extra.tsx。
嵌套面板、图标与隐藏箭头
仓库 demo 还覆盖了这些 ItemType/外观组合:
- 嵌套面板(Nested panel):见 demo/mix.tsx,一个面板的
children里再放一层 Collapse,实现两级收纳。 - 自定义展开图标(expandIcon):见 demo/icon.tsx,可通过
expandIcon={(panelProps) => ...}完全替换箭头图标;面板标题中也支持混排图标。图标由.anticon包裹或裸<svg>渲染时,style/index.ts 对裸<svg>额外做了inline-block+vertical-align: middle处理,确保任何来源的图标都与标题文字垂直居中——这对 Tailwind Preflight 等强制svg { display: block }的 CSS Reset 环境尤为重要。 - 无箭头面板:见 demo/noarrow.tsx,
showArrow={false}时不再渲染箭头图标。注意 ItemType 表的约束:如果showArrow={false},面板的collapsible不能再设成icon(否则点击区域不存在)。CollapsePanel源码中showArrow默认值为true,隐藏箭头时会追加${prefixCls}-no-arrow类(CollapsePanel.tsx)。
更多面板外观组合
- Borderless(无边框):demo/borderless.tsx 展示
bordered={false},容器不再有外边框、内容区背景透明,仅保留面板间的分隔线。 - Ghost Collapse(幽灵面板):demo/ghost.tsx 展示
ghost,在无边框基础上进一步去掉面板间分隔线并让背景完全透明,适合嵌在卡片或其他容器内部。 - 自定义面板(Custom Panel):demo/custom.tsx 演示了
items各字段的组合玩法(label、extra、自定义展开图标等)。
Collapse.Panel(已废弃的写法)
5.6.0 之前使用Collapse.Panel作为子组件逐面板配置。官方文档明确标记为Deprecated:使用 v5.6.0+ 时优先使用items配置。其完整属性表为:
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| collapsible | Specify whether the panel be collapsible or the trigger area | header|icon|disabled | - | 4.9.0(icon: 4.24.0) |
| extra | The extra element in the corner | ReactNode | - | |
| forceRender | Forced render of content on panel, instead of lazy rendering after clicking on header | boolean | false | |
| header | Title of the panel | ReactNode | - | |
| key | Unique key identifying the panel from among its siblings | string | number | - | |
| showArrow | If false, panel will not show arrow icon. 若为 false,则 collapsible 不能设为icon | boolean | true |
传统写法大致如下:
<Collapse defaultActiveKey={['1']}> <Collapse.Panel header="This is panel header 1" key="1"> <p>{text}</p> </Collapse.Panel> <Collapse.Panel header="This is panel header 2" key="2"> <p>{text}</p> </Collapse.Panel> </Collapse>从实现看,Collapse.Panel是对底层RcCollapse.Panel的极薄封装(CollapsePanel.tsx),仅负责统一prefixCls、处理showArrow类名与disabled废弃告警;而Collapse组件本身通过Object.assign(Collapse, { Panel: CollapsePanel })挂载子组件(Collapse.tsx)。官方之所以废弃Collapse.Panel,是因为父组件 API(activeKey、accordion、collapsible 等)更便于通过items数据结构化传递与类型推导(CollapseProps['items']提供完整的 TypeScript 提示)。
Semantic DOM:语义化结构与 classNames / styles 定制
6.0.0 起 Collapse 支持按语义节点做样式定制。Semantic DOM 定义在 demo/_semantic.tsx,共包含五个可定制节点:
| 语义节点 | 说明 | classNames/styles 支持版本 |
|---|---|---|
| root | 根元素,控制容器整体布局与外观(边框、圆角、背景) | 6.0.0 |
| header | 面板头部:flex 布局、内边距、颜色、行高、光标、过渡动画等交互样式 | 5.21.0 |
| title | 标题文字:flex 自适应布局与排版 | 6.0.0 |
| body | 内容区:内边距、颜色、背景等展示样式 | 5.21.0 |
| icon | 展开/收起箭头:字号、过渡动画、旋转变换 | 6.0.0 |
对应的类型定义见 Collapse.tsx,classNames/styles均可传静态对象或函数(函数接收{ props },可按props.size、props.accordion等动态返回)。注意函数形态只在 6.0.0 才支持,相关类型由useMergeSemantic/GenerateSemantic推导(Collapse.tsx)。
下面是参照 demo/style-class.tsx 的用法("Custom semantic dom styling",6.0.0 新增):
import { Collapse, Flex } from 'antd'; import type { CollapseProps, GetProp } from 'antd'; import { createStaticStyles } from 'antd-style'; // 1) 对象写法:直接给各语义节点覆盖 style const styles: CollapseProps['styles'] = { root: { backgroundColor: '#fafafa', border: '1px solid #e0e0e0', borderRadius: 8 }, header: { backgroundColor: '#f0f0f0', padding: '12px 16px', color: '#141414' }, }; // 2) 函数写法:根据 props 动态返回 style const stylesFn: CollapseProps['styles'] = ({ props }): GetProp<CollapseProps, 'styles', 'Return'> => { if (props.size === 'large') { return { root: { backgroundColor: '#fff', border: '1px solid #696FC7', borderRadius: 8 }, header: { backgroundColor: '#F5EFFF', padding: '12px 16px', color: '#141414' }, }; } }; const App: React.FC = () => { const sharedProps: CollapseProps = { classNames: createStaticStyles(({ css }) => ({ root: css`background-color: #fafafa; border: 1px solid #e0e0e0; border-radius: 8px;`, })), items: [{ key: '1', label: 'This is panel header 1', children: <p>...</p> }], }; return ( <Flex vertical gap="medium"> <Collapse {...sharedProps} defaultActiveKey={['1']} styles={styles} /> <Collapse {...sharedProps} defaultActiveKey={['2']} styles={stylesFn} size="large" /> </Flex> ); };同时,ItemType 层面还支持header/body两个更细粒度的语义槽(classNames/styles,5.21.0 起),实现"同一个 Collapse 里不同面板样式不同"的效果。需要说明的是:此能力是 cssinjs 体系下官方推荐的"精准定制"手段,相比依赖深层 DOM 选择器覆盖,语义化 API 的类名在 hash 化后依然稳定、不受内部 DOM 结构调整影响。仓库中配套的测试文件 demo-semantic.test.tsx 与 semantic.test.tsx 会对这些结构做渲染级验证。
Design Token:组件级主题令牌
Collapse 的全部组件令牌定义在 style/index.ts 的ComponentToken接口,并通过prepareComponentToken(style/index.ts)给出由全局 alias token 推导的默认值。官方文档的 Design Token 表格(由<ComponentTokenTable component="Collapse">动态渲染)即来自该接口。可用令牌一览:
| Token | 语义 | 默认值来源(由 alias token 推导) |
|---|---|---|
| headerPadding | 面板头部内边距 | paddingSM padding(默认主题下约为12px 16px) |
| headerPaddingSM | 小尺寸面板头部内边距 | paddingXS paddingSM paddingXS paddingXS |
| headerPaddingLG | 大尺寸面板头部内边距 | padding paddingLG padding padding |
| headerBg | 面板头部背景色 | colorFillAlter |
| contentPadding | 面板内容区内边距 | padding 16(16 为固定值) |
| contentPaddingSM | 小尺寸内容区内边距 | paddingSM |
| contentPaddingLG | 大尺寸内容区内边距 | paddingLG |
| contentBg | 面板内容区背景色 | colorBgContainer |
| borderlessContentPadding | 无边框(borderless/ghost)内容区内边距 | paddingXXS 16 padding |
| borderlessContentBg | 无边框内容区背景色 | transparent |
源码中headerPadding等头部内边距会区分大中小三档:大号走headerPaddingLG与contentPaddingLG,小号走headerPaddingSM与contentPaddingSM,默认走基础令牌,并在genBaseStyle中通过& -small/&-large选择器落地(style/index.ts)。此外代码内部还合并了一个非导出的派生令牌collapsePanelBorderRadius,其值取borderRadiusLG,用于根容器与首/末面板头的圆角衔接,保证圆角视觉统一(style/index.ts)。
覆盖方式有两种:
// 1) ConfigProvider 全局覆盖 import { ConfigProvider } from 'antd'; <ConfigProvider theme={{ components: { Collapse: { headerBg: '#f5f5f5', contentPadding: '20px 24px', headerPadding: '12px 20px', }, }, }} > <App /> </ConfigProvider>; // 2) 主题算法 token 级别覆盖与语义化styles相比,Design Token 更适合团队级的全局主题统一(暗色模式、品牌色换肤),其改动会平滑传递到所有 Collapse 实例。
在 ConfigProvider 中全局统一配置
结合 API 表中 Global Config 一列(部分能力为 ×,即不可全局化)与 Collapse.tsx 的实现可以看到,Collapse 已接入useComponentConfig('collapse'),支持以下能力在 ConfigProvider 层全局下发:className/style/classNames/styles、expandIcon(5.15.0 起)。可用的全局覆盖属性从CollapseSemanticType(Collapse.tsx)与contextExpandIcon的读取逻辑(Collapse.tsx)可见一斑:
<ConfigProvider componentConfig={{ Collapse: { styles: { header: { fontWeight: 600 } }, expandIcon: (props) => <span>{props.isActive ? '−' : '+'}</span>, }, }} >而accordion、collapsible、bordered、ghost、size、activeKey等行为性/状态性属性属于组件实例语义,官方 API 表标记为 ×,不能全局下发——这与 ant-design 对 componentConfig 的通用设计一致(通用组件 props 的全局配置说明可参阅 docs/react/common-props 相关文档,本仓库对应说明位于 docs/react 目录)。
可访问性与测试保障
Collapse 在仓库中配有完整测试:行为测试 index.test.tsx、无障碍专项测试 accessibility.test.tsx 与 a11y.test.ts、demo 回归测试 demo.test.ts 及图片回归 image.test.ts。无障碍实现要点(可从 Collapse.tsx 源码核对):
- 展开箭头在可交互时携带
aria-label(expanded/collapsed),不可交互时标为aria-hidden; - 面板头部是可聚焦元素(
genFocusStyle),支持键盘操作展开/收起; - 折叠中的面板通过
leavedClassName(-panel-hidden)从可访问树中移除。
小结
本文围绕官方文档完整走了一遍 ant-design Collapse 的使用全貌:基础/受控用法与手风琴模式、12 项组件属性的默认值与行为(含bordered、ghost、size、collapsible、expandIconPlacement、destroyOnHidden等)、5.6.0+ 推荐的items声明式面板配置、已废弃的Collapse.Panel写法、Semantic DOM 五个语义节点的 classNames/styles 定制、以及 10 个组件级 Design Token 的主题化能力。所有结论均可在 components/collapse 目录下找到对应的源码、样式与测试佐证,官方每个示例的独立 TSX/MD 演示也都可以直接运行参考,便于你在真实项目中按需组合使用。
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考