一个展开和收起的业务组件(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);
      }
    }
  }
}
相关推荐
lh_12545 分钟前
ECharts 地图开发入门
前端·javascript·echarts
jjw_zyfx7 分钟前
成熟的前端vue vite websocket,Django后端实现方案包含主动断开websocket连接的实现
前端·vue.js·websocket
Mikey_n43 分钟前
前台调用接口的方式及速率对比
前端
周之鸥1 小时前
使用 Electron 打包可执行文件和资源:完整实战教程
前端·javascript·electron
我爱吃朱肉1 小时前
HTMLCSS模板实现水滴动画效果
前端·css·css3
机器视觉知识推荐、就业指导1 小时前
开源QML控件:进度条滑动控件(含源码下载链接)
前端·qt·开源·qml
前端snow1 小时前
前端全栈第二课:用typeorm向数据库添加数据---一对多关系
前端·javascript
難釋懷1 小时前
Shell脚本-for循环语法结构
前端·chrome
全栈老李技术面试1 小时前
【高频考点精讲】async/await原理剖析:Generator和Promise的完美结合
前端·javascript·css·vue·html·react·面试题
kadog1 小时前
PubMed PDF下载 cloudpmc-viewer-pow逆向
前端·javascript·人工智能·爬虫·pdf