【React/MUI/CSS】複数行かつ溢れたら3 点リーダーを付けれるコンポーネントを作ろう!

2024/07/30に公開

てんてんてん(..., 3点リーダー)をいい感じにしたい!

フロントエンドの画面表示を実装していて、「数行(コンポーネントを使う側から指定)かつ溢れたら3点リーダーを付けれるコンポーネント」を実装したくなることがあるかと思います。この記事ではそのやり方をメモ程度にまとめていきます。

具体的なUI

こちらは実装後のStorybookのキャプチャです。

どうやるの?実際のコードは?

React, MUIを用いて.tsxに実装する場合の一例を残しておきます。
MUIでなくても、コードを適宜修正すればchakraなどでも大体同じようにして使えるはず!
追記:chakraにはnoOfLinesというpropsがあると同僚エンジニアが教えてくれました!

/**
 * テキストを指定行数で省略表示するコンポーネント
 * @param param0 lineLength: 表示行数
 * @returns Typography
 */
export const EllipsisText = ({
  lineLength = 1,
  sx,
  ...props
}: {
  lineLength?: number
} & Omit<TypographyProps, "overflow" | "textOverflow" | "display">) => {
  return (
    <Typography
      overflow="hidden"
      textOverflow="ellipsis"
      display="-webkit-box"
      sx={{
        WebkitBoxOrient: "vertical",
        WebkitLineClamp: lineLength,
        ...sx,
      }}
      {...props}
    />
  )
}

このコンポーネントの個人的なポイントは、lineLengthをpropsとしているところです。
これにより、コンポーネントを使う側から何行目に3点リーダーを入れるかを決められるので、使い勝手が良くなるかと思います。

※ 3点リーダーは英語ではellipsisと言うようです。

CSSの当て方で詰まった、、、

CSSのpropsの当て方でなかなか上手く苦戦しているときに、こちらの記事↓に出会い救われました!!

それぞれのCSSについては、多分一ヶ月もしたら何をしているか分からなくなるところもあるはずw
分からなくなったら再度ググります。

ついでにStorybookも書いておこう

import { Meta, StoryObj } from "@storybook/react"
import { EllipsisText } from "./EllipsisText"
import { Box } from "@mui/material"

export default {
  title: "components/EllipsisText",
  component: EllipsisText,
  decorators: [
    (Story) => (
      <Box width={300}>
        <Story />
      </Box>
    ),
  ],
} as Meta<typeof EllipsisText>

type Template = StoryObj<typeof EllipsisText>

export const Default: Template = {
  args: {
    children: "テキスト1テキスト2テキスト3テキスト4テキスト5テキスト6テキスト7テキスト8テキスト9テキスト10",
  },
}

export const EllipsisOnSecondLine: Template = {
  args: {
    children: "テキスト1テキスト2テキスト3テキスト4テキスト5テキスト6テキスト7テキスト8テキスト9テキスト10",
    lineLength: 2,
    typographyProps: {},
  },
}

export const EllipsisOnThirdLine: Template = {
  args: {
    children: "テキスト1テキスト2テキスト3テキスト4テキスト5テキスト6テキスト7テキスト8テキスト9テキスト10テキスト11テキスト12テキスト13テキスト14テキスト15",
    lineLength: 3,
    typographyProps: {},
  },
}

この実装をすると、冒頭のスクショと同様のStorybookができあがります!
ポイントとしては、Storybookのdecorators機能を使っているところです。
decoratorsを使うことでStorybookに表示したいコンポーネント(今回でいうEllipsisText)を親コンポーネントでwrapできるようです!

A decorator is a way to wrap a story in extra “rendering” functionality.

今回はテキストを表示する幅を親要素で指定したく、widthを指定したBox(divタグ)で囲ってあげたかったので、それを再現できてちょうどよかったです!

感想

てんてんてん(..., 3点リーダー)の扱いは難しいですね...(てんてんてん)

参考記事

株式会社モニクル

Discussion