封装 tooltip的组件

195 阅读1分钟

工作之余: tooltip共用组件封装

OverflowingText 组件

import { Tooltip, Grid, Typography, SxProps, Theme } from '@mui/material';
import { useRef, useState, useEffect } from 'react';

interface OverflowingTextProps {
  text: string;
  sx?: SxProps<Theme>;
  isGridItem?: boolean; // 是否作为 Grid 项目
}

const OverflowingText: React.FC<OverflowingTextProps> = ({ text, sx, isGridItem = true }) => {
  const textRef = useRef<HTMLDivElement | null>(null);
  const [isOverflowing, setIsOverflowing] = useState<boolean>(false);

  useEffect(() => {
    const el = textRef.current;
    if (el) {
      setIsOverflowing(el.scrollWidth > el.clientWidth); // 检测是否溢出
    }
  }, [text]);

  const content = (
    <Typography
      ref={textRef}
      variant="body2"
      sx={{
        overflow: 'hidden',
        textOverflow: 'ellipsis',
        whiteSpace: 'nowrap',
        ...sx,
      }}
    >
      {text}
    </Typography>
  );

  // 根据是否为 Grid Item 决定外层是否使用 Grid
  const Wrapper = isGridItem ? Grid : 'div';

  return (
    <Tooltip title={isOverflowing ? text : ''} arrow disableInteractive>
      <Wrapper item sx={{ maxWidth: '100%', ...sx }}>
        {content}
      </Wrapper>
    </Tooltip>
  );
};

export default OverflowingText;

代码说明

  1. OverflowingTextProps 接口:定义了 OverflowingText 组件的 props:

    • text:需要显示的文本,必填。
    • sx:可选,MUI 样式属性。
    • isGridItem:可选,布尔值,指示该组件是否作为 Grid 项目使用,默认为 true
  2. textRef:用于获取文本的 DOM 节点,类型为 HTMLDivElement | null

  3. isOverflowing:存储文本是否溢出的状态,类型为 boolean

  4. useEffect:在文本变化时检查内容是否超出可视区域。

  5. content:在 Tooltip 中显示的文本。

使用示例

Grid 中使用

import { Grid, Dialog, Box } from '@mui/material';
import OverflowingText from './OverflowingText';

const MyGridComponent: React.FC = () => {
  return (
    <Dialog open>
      <Box sx={{ padding: 2 }}>
        <Grid container spacing={2}>
          <OverflowingText text="超长文本内容 AAAAAAAAAAAAAAAAAAA" sx={{ xs: 3 }} />
          <OverflowingText text="超长文本内容 BBBBBBBBBBBBBBBBBBBBB" sx={{ xs: 3 }} />
        </Grid>
      </Box>
    </Dialog>
  );
};

export default MyGridComponent;

在导航菜单中使用

import OverflowingText from './OverflowingText';

const NavMenu: React.FC = () => {
  return (
    <div style={{ width: '200px' }}>
      <OverflowingText text="菜单项 - 长标题内容" sx={{ fontSize: '14px' }} isGridItem={false} />
      <OverflowingText text="另一项 - 更多超长标题" sx={{ fontSize: '14px' }} isGridItem={false} />
    </div>
  );
};

export default NavMenu;

总结

通过以上改写,OverflowingText 组件现在支持 TypeScript,能够更好地进行类型检查,提高代码的可靠性和可维护性。你可以根据需要将此组件用于不同的布局中,同时确保在文本溢出时能正常显示 Tooltip