一个展开和收起的业务组件(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);
      }
    }
  }
}
相关推荐
二哈喇子!3 小时前
BOM模型
开发语言·前端·javascript·bom
二哈喇子!3 小时前
Vue2 监听器 watcher
前端·javascript·vue.js
摘星编程3 小时前
OpenHarmony + RN:Bluetooth连接蓝牙外设
react native·react.js·harmonyos
yanyu-yaya3 小时前
前端面试题
前端·面试·前端框架
二哈喇子!3 小时前
使用NVM下载Node.js管理多版本
前端·npm·node.js
GGGG寄了4 小时前
HTML——文本标签
开发语言·前端·html
摘星编程4 小时前
在OpenHarmony上用React Native:ActionSheet确认删除
javascript·react native·react.js
2501_944521594 小时前
Flutter for OpenHarmony 微动漫App实战:推荐动漫实现
android·开发语言·前端·javascript·flutter·ecmascript
Amumu121385 小时前
Vue核心(三)
前端·javascript·vue.js
CoCo的编程之路5 小时前
2026 前端效能革命:如何利用智能助手实现“光速”页面构建?深度横评
前端·人工智能·ai编程·comate·智能编程助手·文心快码baiducomate