WASD TECH BLOG

WASD Inc.のTech Blogです。

MUIのButton Componentの中のアイコンに自作のSVGを使用する方法

WASD Inc. 開発チームのYubaです。

弊社ではUI ComponentライブラリのMUIを活用してComponentを作成しています。

mui.com

その中で、MUIのButtonコンポーネント中のアイコンに自作ののSVGを使用したところ、コンポーネントのスタイルが崩れてしまうという問題が発生しました。 本記事では、その問題の調査から解決に至るまでの過程を紹介します。

問題の背景

弊社のプロダクトのデジちゃいむではGoogleクチコミ連携という機能があり、店舗とGoogle Maps上の店舗のデータとひも付けて、店舗でデジちゃいむを使用したユーザーをGoogle Maps上の店舗のクチコミへ誘導するという機能があります。

この機能を実装するにあたり、今回はこのGoogleでクチコミのボタンを作成しました。

MUIのButton ComponentにはStartIconというPropsの機能があり

SVGのComponentなどをPropsで渡すことで文字列より先頭にアイコンを表示できます。

<Button variant="outlined" startIcon={<DeleteIcon />}>
  Delete
</Button>

mui.com

Googleでクチコミボタンでも同様にGoogle MapsのアイコンのSVGをComponentで独自で作成しstartIconに<GoogleMapIcon/> 渡すように実装を行いました。

 <Button
  variant="contained"
  startIcon={<GoogleMapIcon />}
  sx={{
    backgroundColor: "white",
  }}
 >
  <Typography variant="h5" sx={{ lineHeight: "2em", fontWeight: "bold" }}>
    Google でクチコミ
  </Typography>
 </Button>

この実装ではアイコンのSVGが小さくなってしまう、テキストとのmarginが少し空きすぎてしまうなどの問題が発生しました。

原因と解決策

ChromeのDevToolsで確認するとSVGのstartIconのnth-of-type(1)fontSize:20px が当たっていることがわかり、この影響によりアイコンが小さく表示されているので適切な大きさに上書きをする必要がありました。

.css-1d6wzja-MuiButton-startIcon>*:nth-of-type(1) {
  font-size: 20px;
}

MUIではComponentのclassセレクターを上書きする方法として、ComponentのClassesをimportしsx Propsから上書きをすることができます。この方法はClassesを提供している他のComponentでも使用できます。

mui.com

自前でclassをを定義してclassName経由で渡してスタイルを適用することも可能ですが、importしたClassesをsx Props経由で使う方がTypeScriptで安全に書きやすいです。

sx Propsで .${buttonClasses.startIcon}からstartIconのclassを直接指定して下記の用にmarginを加え、nth-of-type(1) のfontSizeを32pxに指定することでスタイリングの調整ができスタイリングの問題が解消することができました!

import { Button } from "@mui/material";
import { buttonClasses } from "@mui/material/Button";

<Button
  variant="contained"  
  startIcon={<GoogleMapIcon />}
  sx={{
    ...
    [`& .${buttonClasses.startIcon}`]: {
      mt: "-2px",
      mr: "4px",
      "&>*:nth-of-type(1)": {
        fontSize: 32,
      },
    },
  }}
>
  <Typography variant="h5" sx={{ lineHeight: "2em", fontWeight: "bold" }}>
    Google でクチコミ
  </Typography>
</Button>

Classesを使う際の注意点

MUIのComponentのClassesを使う上での注意点ですが、VScodeなどでサジェスト通りのimportを行うと下記のようにClassesを直接importしている場合があるのですが、このimportではbuttonClassesを使用できずエラーが出るので

import { buttonClasses } from "@mui/material/Button/buttonClasses";
import { buttonClasses } from "@mui/material/Button"

この様に書く必要があります。

MUIでは1st Levelと2nd Levelからのimportのみをサポートしていて、それより深い階層のimportはプライベートとみなされるのが理由のようです。

mui.com

まとめ

MUIを使用するとさまざまなコンポーネントを簡単に作成できますが、今回のように特殊なコンポーネントの作成をしたいとなった場合はカスタマイズの方法を調べてを実装を行う必要がありました。プロダクトを作っていくにあたっては特殊な表示の実装を行うことも多いのでMUIを使っていくに当たっての知識もどんどん取り入れていく必要があるなと思いました。

弊社では今後ともMUIを使ってさまざまな物を開発していくので、いろいろなTipsなどを発信していければと思っています!

WASD TECH BLOG では主に React、TypeScript、GraphQL に関する記事を定期的に発信します。

よろしければ他の記事や、もお願いします。