Material-UI で独自のアイコンを表示するコンポーネントを作成する
こんにちは、Gaji-Labo アシスタントエンジニアの石垣です。
今回は、React 用 UI フレームワークである Material-UI で独自の SVG アイコンを出し分けできるようにするアイコンコンポーネントを作成する方法についてまとめたいと思います。
概要
Material-UI には Icon
というコンポーネントが用意されており、Material Design や Font Awesome のアイコンが表示できるようになっています。
Icon
コンポーネントは SvgIcon
というコンポーネントを元にしており、SvgIcon
コンポーネントを使用することで Icon
コンポーネントと同様に独自のアイコンを表示することが出来ます。
今回はこの SvgIcon
を使用して、独自のアイコンを表示するコンポーネントを作成する方法についてまとめます。
SvgIcon で独自のアイコンを表示する
SvgIcon
で独自のアイコンを表示するには、 SvgIcon
コンポーネントで svg
要素をラップします。
import React from "react";
import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
type Props = React.HTMLProps<SvgIconProps>;
export const Icon: React.FC<Props> = (props) => {
return (
<SvgIcon>
<svg width="100" height="100" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" stroke="#000" stroke-width="3" fill="red"/></svg>
</SvgIcon>
);
};
SvgIcon
には、他の Material-UI コンポーネントと同様、 classes, component, fontSize, viewBox などの props がデフォルトで用意されている他、aria-label
aria-hidden
など、追加でアイコンに必要な属性を props として指定することも可能です。
SvgIcon の props については公式のAPIドキュメントをご参照ください。
import React from "react";
import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
interface Props extends React.HTMLProps<SvgIconProps> {
ariaHidden?: boolean;
ariaLabel?: string;
className?: string;
}
export const Icon: React.FC<Props> = (props) => {
const {
ariaHidden,
ariaLabel,
className,
} = props;
return (
<SvgIcon
aria-hidden={ariaHidden}
aria-label={ariaLabel}
className={className}
component="span"
viewBox=""
>
<svg width="100" height="100" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" stroke="#000" stroke-width="3" fill="red"/></svg>
</SvgIcon>
);
};
デフォルトでは svg
要素としてレンダリングされますが、テキストと同時に扱うことを考慮して component
props で span
要素に変更しています。
それに伴い viewBox
を空にしています。デフォルトでは '0 0 24 24'
が指定されます。
スタイルを上書きしたい場合は、以前「React + Material-UIを使用してMaterial Designのコンポーネントを作成する」でご紹介したやり方と同様、 createMuiTheme
で上書きすることができます。
...
import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
...
const theme = createMuiTheme({
overrides: {
MuiSvgIcon: {
root: {
color: "inherit",
fontSize: "inherit",
height: "auto",
lineHeight: 0,
width: "auto",
"& > svg": {
height: "1em",
width: "1em",
},
},
},
},
});
return (
<ThemeProvider theme={theme}>
<SvgIcon
aria-hidden={ariaHidden}
aria-label={ariaLabel}
className={className}
component="span"
viewBox=""
>
<svg width="100" height="100" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" stroke="#000" stroke-width="3" fill="red"/></svg>
</SvgIcon>
</ThemeProvider>
);
};
...
<Icon />
<br />
Circle
...
複数のアイコンを出し分けするコンポーネントを作成する
先程作成したコンポーネントでは1つのアイコンしか表示できないため、出し分けできるように変更します。
import React from "react";
import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import Circle from "../assets/icons/Circle.svg";
import Line from "../assets/icons/Line.svg";
const iconList: { [name: string]: JSX.Element } = {
circle: <Circle />,
line: <Line />,
};
interface Props extends React.HTMLProps<SvgIconProps> {
iconName: "circle" | "line";
}
export const Icon: React.FC<Props> = (props) => {
const { iconName } = props;
return <SvgIcon>{iconList[iconName]}</SvgIcon>;
};
iconName
props を追加し、渡ってきた iconName で circle
が渡ってきた時は <Circle />
コンポーネントを表示させるなどしてそれぞれの svg を表示させています。
svg を React コンポーネントとして扱うため、react-svg-loader
を導入する必要があります。
<Icon iconName="circle" />
<br />
Circle
...
<Icon iconName="line" />
<br />
Line
これで複数のアイコンを出し分けするコンポーネントを作成することが出来ました。
まとめ
今回は Material-UI で独自の SVG アイコンを表示するコンポーネントの作成方法についてまとめました。
Material-UI を使用している方、興味を持っている方の参考にしていただけたらと思います。
Gaji-Laboでは、JavaScriptフレームワーク経験が豊富なパートナーさんを募集しています
Gaji-Laboでは、開発チームの一員としてプロジェクトに一緒に取り組んでくれる業務委託のパートナーさんを募集しています。
現在は特にJavaScriptフレームワーク実践と業務経験が豊富なWebフロントエンドエンジニアを必要としています。React + TypeScript、Vue.js、Next.js、Nuxt.js など、あなたの得意なフレームワークを教えて下さい!
パートナー契約へのお問い合わせもお仕事へのお問い合わせも、どちらもいつでも大歓迎です。まずはオンラインでのリモート面談からはじめましょう。ぜひお気軽にお問い合わせください!
お問い合わせしてみる!