React+TypeScript で作る SVG のためのシンプルな Icon コンポーネント

はじめに

こんにちは kimizuy です。

今回は React と TypeScript で複数の SVG を一括で管理するためのシンプルな Icon コンポーネントをご紹介します。

アイコンを専用のコンポーネントで管理することで、サイズやスタイルのインターフェイスも統一できアイコンの新規追加も簡単になります。

tldr

コード例を以下に示します(リポジトリ)。

// src/icon.tsx
import { ReactComponent as Empty } from './icon/mood-empty.svg'
import { ReactComponent as Happy } from './icon/mood-happy.svg'
import { ReactComponent as Sad } from './icon/mood-sad.svg'

const icons = { Empty, Happy, Sad }

type Name = keyof typeof icons

type Props = {
  name: Name
  size?: number
  className?: string
}

const DEFAULT_SIZE = 24

export function Icon({ name, size = DEFAULT_SIZE, className }: Props) {
  const SvgComponent = icons[name]

  return (
    <SvgComponent
      style={{ height: `${size}px`, width: `${size}px` }}
      className={className}
    />
  )
}

簡単にまとめると icons に SVG コンポーネントを列挙し、Icon コンポーネントの中でブラケット記法を利用して呼び出します。新規のアイコンは icons に追加していくだけです。

const icons = { Empty, Happy, Sad }

Name 型はオブジェクトのキーを取得して、ユニオン型を作成しています。これで型の恩恵を受けることができ、アイコンの名前を間違える心配もありません。

type Name = keyof typeof icons

style props でアイコンのサイズを指定することで .svg ファイル側にある width height 属性を上書きすることができます。

    <SvgComponent
      style={{ width: `${size}px`, height: `${size}px` }}
      className={className}
    />

使い方

Icon コンポーネントは以下のように利用します。

// src/App.tsx
import './App.css'
import { Icon } from './icon'

function App() {
  return (
    <div className="App">
      <div className="Icons-wrapper">
        <div>
          <Icon name="Empty" />
        </div>
        <div>
          <Icon name="Happy" className="Icon-orange" />
        </div>
        <div>
          <Icon name="Sad" size={100} />
        </div>
      </div>
    </div>
  )
}

export default App

補足

今回の記事は create-react-app を使ってデモを作成しました。create-react-app プロジェクトはビルトインで SVG が使えます。環境によって SVG コンポーネントのインポート方法が異なる場合は適宜読み替えてください。

Adding SVGs

import { ReactComponent as Empty } from './icon/mood-empty.svg'

おわりに

今回はシンプルな Icon コンポーネントについてご紹介しました。個人的にミニマルな感じで書くことができて気に入っています。

以上、お読みいただきありがとうございました。

この機会に、オンラインで気軽に面談してみませんか?

現在弊社では一緒にお仕事をしてくださるエンジニアさんやデザイナーさんを積極募集しています。まずはカジュアルな面談で、お互いに大事にしていることをお話できたらうれしいです。詳しい応募要項は以下からチェックしてください。

パートナー契約へのお問い合わせもお仕事へのお問い合わせも、どちらもいつでも大歓迎です。まずはオンラインでのリモート面談からはじめましょう。ぜひお気軽にお問い合わせください!

お問い合わせしてみる!

投稿者 Yamasaki Kimizu

React, Redux, TypeScript プロジェクトでフロントエンド領域を担当。個人でも Next.js アプリの開発をしています。日課はRSSで取得した技術記事を読むこと、最近の関心は Core Web Vitals です。将来はでかい犬が飼いたいです。