一个展开和收起的业务组件(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);
      }
    }
  }
}
相关推荐
Csvn2 小时前
OpenSpec 详细使用教程
前端
王莎莎-MinerU3 小时前
MinerU 深度技术解析:从架构原理到生产部署的全面指南
css·人工智能·自然语言处理·架构·ocr·个人开发
之歆3 小时前
Day19_LESS 完全指南——从入门到工程实践
前端·css·less
云水一下4 小时前
HTML5 从入门到精通:实战收官——从零搭建完整静态网站,综合运用所有知识
前端·html5
不总是4 小时前
Windows 系统 Node.js 免安装版(zip)安装与配置教程(2026 最新)
前端·windows·node.js
冬奇Lab4 小时前
每日一个开源项目(第105篇):Twenty - 跳出 Salesforce 的圈套,定义现代开源 CRM
前端·后端·开源
zhangyao9403305 小时前
开发pc端时,表格的高度怎么设置才能铺满页面
前端·javascript·elementui
kjs--5 小时前
浏览器书签执行脚本
前端
之歆5 小时前
Day16_JavaScript 轮播图与事件工程实战(下篇)
服务器·开发语言·前端·javascript·网络·性能优化
沄媪5 小时前
CSRF 跨站请求伪造
前端·ctf·csrf