feat(Collapse): Collapse support for setting size (#40286)

Co-authored-by: Yuiai01 <dujiaqi@kezaihui.com>
pull/40464/head
JiaQi 2 years ago committed by GitHub
parent 1fc374495f
commit 9d51345f90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,6 +11,8 @@ import initCollapseMotion from '../_util/motion';
import { cloneElement } from '../_util/reactNode';
import warning from '../_util/warning';
import type { CollapsibleType } from './CollapsePanel';
import type { SizeType } from '../config-provider/SizeContext';
import SizeContext from '../config-provider/SizeContext';
import CollapsePanel from './CollapsePanel';
import useStyle from './style';
@ -34,6 +36,7 @@ export interface CollapseProps {
expandIcon?: (panelProps: PanelProps) => React.ReactNode;
expandIconPosition?: ExpandIconPosition;
ghost?: boolean;
size?: SizeType;
collapsible?: CollapsibleType;
children?: React.ReactNode;
}
@ -57,14 +60,19 @@ type CompoundedComponent = React.FC<CollapseProps> & {
const Collapse: CompoundedComponent = (props) => {
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const size = React.useContext(SizeContext);
const {
prefixCls: customizePrefixCls,
className,
rootClassName,
bordered = true,
ghost,
size: customizeSize,
expandIconPosition = 'start',
} = props;
const mergedSize = customizeSize || size || 'middle';
const prefixCls = getPrefixCls('collapse', customizePrefixCls);
const rootPrefixCls = getPrefixCls();
const [wrapSSR, hashId] = useStyle(prefixCls);
@ -105,6 +113,7 @@ const Collapse: CompoundedComponent = (props) => {
[`${prefixCls}-borderless`]: !bordered,
[`${prefixCls}-rtl`]: direction === 'rtl',
[`${prefixCls}-ghost`]: !!ghost,
[`${prefixCls}-${mergedSize}`]: mergedSize !== 'middle',
},
className,
rootClassName,

@ -1438,3 +1438,170 @@ exports[`renders ./components/collapse/demo/noarrow.tsx extend context correctly
</div>
</div>
`;
exports[`renders ./components/collapse/demo/size.tsx extend context correctly 1`] = `
Array [
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
role="separator"
>
<span
class="ant-divider-inner-text"
>
Default Size
</span>
</div>,
<div
class="ant-collapse ant-collapse-icon-position-start"
>
<div
class="ant-collapse-item"
>
<div
aria-disabled="false"
aria-expanded="false"
class="ant-collapse-header"
role="button"
tabindex="0"
>
<div
class="ant-collapse-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right ant-collapse-arrow"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
<span
class="ant-collapse-header-text"
>
This is default size panel header
</span>
</div>
</div>
</div>,
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
role="separator"
>
<span
class="ant-divider-inner-text"
>
Small Size
</span>
</div>,
<div
class="ant-collapse ant-collapse-icon-position-start ant-collapse-small"
>
<div
class="ant-collapse-item"
>
<div
aria-disabled="false"
aria-expanded="false"
class="ant-collapse-header"
role="button"
tabindex="0"
>
<div
class="ant-collapse-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right ant-collapse-arrow"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
<span
class="ant-collapse-header-text"
>
This is small size panel header
</span>
</div>
</div>
</div>,
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
role="separator"
>
<span
class="ant-divider-inner-text"
>
Large Size
</span>
</div>,
<div
class="ant-collapse ant-collapse-icon-position-start ant-collapse-large"
>
<div
class="ant-collapse-item"
>
<div
aria-disabled="false"
aria-expanded="false"
class="ant-collapse-header"
role="button"
tabindex="0"
>
<div
class="ant-collapse-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right ant-collapse-arrow"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
<span
class="ant-collapse-header-text"
>
This is large size panel header
</span>
</div>
</div>
</div>,
]
`;

@ -1356,3 +1356,170 @@ exports[`renders ./components/collapse/demo/noarrow.tsx correctly 1`] = `
</div>
</div>
`;
exports[`renders ./components/collapse/demo/size.tsx correctly 1`] = `
Array [
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
role="separator"
>
<span
class="ant-divider-inner-text"
>
Default Size
</span>
</div>,
<div
class="ant-collapse ant-collapse-icon-position-start"
>
<div
class="ant-collapse-item"
>
<div
aria-disabled="false"
aria-expanded="false"
class="ant-collapse-header"
role="button"
tabindex="0"
>
<div
class="ant-collapse-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right ant-collapse-arrow"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
<span
class="ant-collapse-header-text"
>
This is default size panel header
</span>
</div>
</div>
</div>,
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
role="separator"
>
<span
class="ant-divider-inner-text"
>
Small Size
</span>
</div>,
<div
class="ant-collapse ant-collapse-icon-position-start ant-collapse-small"
>
<div
class="ant-collapse-item"
>
<div
aria-disabled="false"
aria-expanded="false"
class="ant-collapse-header"
role="button"
tabindex="0"
>
<div
class="ant-collapse-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right ant-collapse-arrow"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
<span
class="ant-collapse-header-text"
>
This is small size panel header
</span>
</div>
</div>
</div>,
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
role="separator"
>
<span
class="ant-divider-inner-text"
>
Large Size
</span>
</div>,
<div
class="ant-collapse ant-collapse-icon-position-start ant-collapse-large"
>
<div
class="ant-collapse-item"
>
<div
aria-disabled="false"
aria-expanded="false"
class="ant-collapse-header"
role="button"
tabindex="0"
>
<div
class="ant-collapse-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right ant-collapse-arrow"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
<span
class="ant-collapse-header-text"
>
This is large size panel header
</span>
</div>
</div>
</div>,
]
`;

@ -39,6 +39,14 @@ describe('Collapse', () => {
expect(asFragment().firstChild).toMatchSnapshot();
});
it('should be able to config size', () => {
const { container: small } = render(<Collapse size="small" />);
const { container: large } = render(<Collapse size="large" />);
expect(small.querySelector('.ant-collapse')).toHaveClass('ant-collapse-small');
expect(large.querySelector('.ant-collapse')).toHaveClass('ant-collapse-large');
});
it('should keep the className of the expandIcon', () => {
const { container } = render(
<Collapse

@ -0,0 +1,11 @@
## zh-CN
折叠面板有大、中、小三种尺寸。
通过设置 `size``large` `small` 分别把折叠面板设为大、小尺寸。若不设置 `size`,则尺寸为中。
## en-US
Ant Design supports a default collapse size as well as a large and small size.
If a large or small collapse is desired, set the `size` property to either `large` or `small` respectively. Omit the `size` property for a collapse with the default size.

@ -0,0 +1,35 @@
import React from 'react';
import { Collapse, Divider } from 'antd';
const { Panel } = Collapse;
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 App: React.FC = () => (
<>
<Divider orientation="left">Default Size</Divider>
<Collapse>
<Panel header="This is default size panel header" key="1">
<p>{text}</p>
</Panel>
</Collapse>
<Divider orientation="left">Small Size</Divider>
<Collapse size="small">
<Panel header="This is small size panel header" key="1">
<p>{text}</p>
</Panel>
</Collapse>
<Divider orientation="left">Large Size</Divider>
<Collapse size="large">
<Panel header="This is large size panel header" key="1">
<p>{text}</p>
</Panel>
</Collapse>
</>
);
export default App;

@ -16,6 +16,7 @@ A content area which can be collapsed and expanded.
<!-- prettier-ignore -->
<code src="./demo/basic.tsx">Collapse</code>
<code src="./demo/size.tsx">Size</code>
<code src="./demo/accordion.tsx">Accordion</code>
<code src="./demo/mix.tsx">Nested panel</code>
<code src="./demo/borderless.tsx">Borderless</code>
@ -40,6 +41,7 @@ A content area which can be collapsed and expanded.
| expandIcon | Allow to customize collapse icon | (panelProps) => ReactNode | - | |
| expandIconPosition | Set expand icon position | `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` \| `middle` \| `small` | `middle` | 5.2.0 |
| onChange | Callback function executed when active panel is changed | function | - | |
### Collapse.Panel

@ -17,6 +17,7 @@ cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*B7HKR5OBe8gAAAAAAA
<!-- prettier-ignore -->
<code src="./demo/basic.tsx">折叠面板</code>
<code src="./demo/size.tsx">面板尺寸</code>
<code src="./demo/accordion.tsx">手风琴</code>
<code src="./demo/mix.tsx">面板嵌套</code>
<code src="./demo/borderless.tsx">简洁风格</code>
@ -41,6 +42,7 @@ cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*B7HKR5OBe8gAAAAAAA
| expandIcon | 自定义切换图标 | (panelProps) => ReactNode | - | |
| expandIconPosition | 设置图标位置 | `start` \| `end` | - | 4.21.0 |
| ghost | 使折叠面板透明且无边框 | boolean | false | 4.4.0 |
| size | 设置折叠面板大小 | `large` \| `middle` \| `small` | `middle` | 5.2.0 |
| onChange | 切换面板的回调 | function | - | |
### Collapse.Panel

@ -9,6 +9,8 @@ type CollapseToken = FullToken<'Collapse'> & {
collapseContentBg: string;
collapseHeaderBg: string;
collapseHeaderPadding: string;
collapseHeaderPaddingSM: string;
collapseHeaderPaddingLG: string;
collapsePanelBorderRadius: number;
collapseContentPaddingHorizontal: number;
};
@ -21,6 +23,8 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
collapseContentPaddingHorizontal,
collapseHeaderBg,
collapseHeaderPadding,
collapseHeaderPaddingSM,
collapseHeaderPaddingLG,
collapsePanelBorderRadius,
lineWidth,
@ -30,9 +34,11 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
colorTextHeading,
colorTextDisabled,
fontSize,
fontSizeLG,
lineHeight,
marginSM,
paddingSM,
paddingLG,
motionDurationSlow,
fontSizeIcon,
} = token;
@ -141,6 +147,34 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
},
},
[`&-small`]: {
[`> ${componentCls}-item`]: {
[`> ${componentCls}-header`]: {
padding: collapseHeaderPaddingSM,
},
[`> ${componentCls}-content > ${componentCls}-content-box`]: {
padding: paddingSM,
},
},
},
[`&-large`]: {
[`> ${componentCls}-item`]: {
fontSize: fontSizeLG,
[`> ${componentCls}-header`]: {
padding: collapseHeaderPaddingLG,
[`> ${componentCls}-expand-icon`]: {
height: fontSizeLG * lineHeight,
},
},
[`> ${componentCls}-content > ${componentCls}-content-box`]: {
padding: paddingLG,
},
},
},
[`${componentCls}-item:last-child`]: {
[`> ${componentCls}-content`]: {
borderRadius: `0 0 ${collapsePanelBorderRadius}px ${collapsePanelBorderRadius}px`,
@ -254,6 +288,8 @@ export default genComponentStyleHook('Collapse', (token) => {
collapseContentBg: token.colorBgContainer,
collapseHeaderBg: token.colorFillAlter,
collapseHeaderPadding: `${token.paddingSM}px ${token.padding}px`,
collapseHeaderPaddingSM: `${token.paddingXS}px ${token.paddingSM}px`,
collapseHeaderPaddingLG: `${token.padding}px ${token.paddingLG}px`,
collapsePanelBorderRadius: token.borderRadiusLG,
collapseContentPaddingHorizontal: 16, // Fixed value
});

@ -12329,7 +12329,7 @@ exports[`ConfigProvider components Collapse configProvider componentDisabled 1`]
exports[`ConfigProvider components Collapse configProvider componentSize large 1`] = `
<div
class="config-collapse config-collapse-icon-position-start"
class="config-collapse config-collapse-icon-position-start config-collapse-large"
>
<div
class="config-collapse-item"

Loading…
Cancel
Save