index.tsx
typescript
import classNames from 'classnames';
import { useBoolean } from 'ahooks';
import { useMemo } from 'react';
import styles from './index.module.less';
type IProps = {
foldHeight?: string | number;
} & React.HTMLAttributes<HTMLDivElement>;
// 默认折叠高度
const DEFAULT_FOLD_HEIGHT = 200;
/**
* 用于折叠展开的组件
* @param props
* @returns
*/
const FoldBlock = (props: IProps) => {
const [open, { toggle }] = useBoolean(false);
const height = useMemo(() => {
return typeof props?.foldHeight === 'number'
? `${props?.foldHeight ?? DEFAULT_FOLD_HEIGHT}px`
: props?.foldHeight || `${DEFAULT_FOLD_HEIGHT}px`;
}, [props?.foldHeight]);
return (
<div
className={classNames(styles.foldBlockSwapper, props?.className)}
style={{ height: open ? 'auto' : height, ...(props?.style || {}) }}
>
{props?.children}
<div className={styles.toggleBox}>
<div className={styles.splitLine} />
<div className={styles.toggleBtn} onClick={toggle}>
{open ? '收起' : '展开'}
<span className={classNames(styles.toggleTriangle, open && styles.toggleTriangleOpen)} />
</div>
<div className={styles.splitLine} />
</div>
</div>
);
};
export default FoldBlock;
index.module.less
css
.foldBlockSwapper {
position: relative;
padding-bottom: 44px;
overflow: hidden;
.toggleBox {
position: absolute;
bottom: 0;
left: 0;
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
width: 100%;
height: 44px;
padding: 0 24px;
padding-bottom: 16px;
background-color: #fff;
.splitLine {
flex: 1;
height: 1px;
background-color: #e0e0e0;
transform: scaleY(0.5);
}
.toggleBtn {
display: flex;
align-items: center;
justify-content: center;
padding: 5px 26px;
color: #0068ff;
cursor: pointer;
.toggleTriangle {
display: inline-block;
width: 6px;
height: 6px;
margin-left: 8px;
border-top: 1px solid #0068ff;
border-right: 1px solid #0068ff;
transform: rotate(135deg);
}
.toggleTriangleOpen {
transform: rotate(315deg);
}
}
}
}