一个展开和收起的业务组件(React)

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);
      }
    }
  }
}
相关推荐
陈随易4 分钟前
副业搞钱点子之赛事与活动
前端·后端·程序员
电梯界知识分子6 分钟前
景德镇老房重新设计阶段规划楼梯与电梯,1.7m×1.6m空间装400kg观光电梯,棕色框架茶色玻璃适配中式装修
大数据·服务器·前端·网络·家用电梯
Shell运维手记15 分钟前
Shell 脚本入门课堂讲解
前端·chrome
Profile排查笔记18 分钟前
有哪些开源指纹浏览器项目?先核对客户端、内核与许可证
前端·人工智能·后端·自动化
CodeGL23 分钟前
16、Python Web开发
开发语言·前端·python
FRing0331 分钟前
JavaScript入门到精通二十九(内置构造函数(Object、Array))
开发语言·前端·javascript
AAA程序技术36 分钟前
从 DOM 到屏幕:浏览器渲染管线六步拆解
前端·浏览器
zach36 分钟前
useContext 深入讲解:组件透传、原理与最佳实践
前端
张一凡9343 分钟前
AI 改完代码,人却不知道它改了什么:架构漂移才是真正的成本
前端·后端·agent
sycmancia44 分钟前
Qml——Text元素
java·前端·html