GatsbyJSで作ったブログでcolor modeに応じてアイコンの色を変える

公開日: 2020年06月11日最終更新日: 2021年10月17日

biographyにTwitterやGitHubのアイコンを表示して、そのアイコンをクリックするとSNSのページに飛ぶようにしたいと思いました。

bio-contentにSNSアイコンを追加

アイコン表示とリンクを貼るだけならば、以下のようにするだけです。TwitterとGitHubのアイコンはmaterial-uiのものをimportしています。
ただし、これでは色がリンクテキストの色になってしまいます。また、GitHubのアイコンは白黒なのでdark / lightのモード切替で背景の色に同化してしまいます。できれば、モードに応じてGitHubアイコンの色を変更したいです。

src\gatsby-theme-blog\components\bio-content.js

import { Styled } from 'theme-ui'
import { Fragment } from "react"
import TwitterIcon from '@material-ui/icons/Twitter';
import GitHubIcon from '@material-ui/icons/GitHub';

/**
 * Change the content to add your own bio
 */

export default () => (
  <Fragment>
    <Styled.a href="https://gan0803.dev/">Gan0803</Styled.a>
    <br />
    ソフトウェアエンジニア
    <br />
    Androidやってます。趣味は宇宙開発です。
    <br />
    <Styled.a href="https://twitter.com/Gan0803" target="_blank" rel="noopener noreferrer">
      <TwitterIcon />
    </Styled.a>
    <Styled.a href="https://github.com/Gan0803" target="_blank" rel="noopener noreferrer">
      <GitHubIcon />
    </Styled.a>
  </Fragment>
)

Color Modes

gatsby-theme-blogにはcolor modeの切り替えが組み込まれています。これに合わせてアイコンの色を変化させます。

gatsby-theme-blogはTheme UIを使ってcolor modeを実現しています。theme-uiを使うためにgatsby-plugin-theme-uiをimportしており、これはTheme UIをGatsbyJSで簡単に扱えるようにしたものです。

Theme UIのColor Modesに説明がありますが、modeごとの色の指定は以下のように記載します。modesの中のdarkと記載されたブロックがdark modeの色指定です。

// example theme colors
{
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#07c',
    modes: {
      dark: {
        text: '#fff',
        background: '#000',
        primary: '#0cf',
      }
    }
  }
}

これと同様にアイコンの色も指定できると便利です。ですがここで定義した色をjavascriptからどの様に参照するかがまだわかりません。 これは調べるのに時間がかかりましたがThe sx propを使うことにしました。ちなみにStyledに取り込んだり、Variantで参照したりする事もできそうです。

まず、colors.jsにgithubという名前で色の指定を追記します。

src\gatsby-theme-blog\gatsby-plugin-theme-ui\colors.js

import merge from "deepmerge"
import defaultThemeColors from "gatsby-theme-blog/src/gatsby-plugin-theme-ui/colors"

/*
 * Want to change your theme colors?
 * Try uncommenting the color overrides below
 * to go from default purple to a blue theme
 */

const darkBlue = `#007acc`
const lightBlue = `#66E0FF`
const blue = `#36A0AF`
const blueGray = `#282c35`
const white = `#FFFFFF`
const black = '#000000'

export default merge(defaultThemeColors, {
  text: blueGray,
  primary: darkBlue,
  heading: blueGray,
  github: black,
  modes: {
    dark: {
      background: blueGray,
      primary: lightBlue,
      highlight: blue,
      github: white,
    },
  },
})

上記で指定した色はsx={{margin: 10, color: 'github'}}の様に読み込むことができます。 sx propを使う場合、ファイルの先頭に/** @jsx jsx */を記載し、import { jsx } from 'theme-ui'する必要があります。

src\gatsby-theme-blog\components\bio-content.js

/** @jsx jsx */
import { jsx, Styled } from 'theme-ui'
import { Fragment } from "react"
import TwitterIcon from '@material-ui/icons/Twitter';
import GitHubIcon from '@material-ui/icons/GitHub';
import { Link } from "gatsby"
import ExtLink from '@material-ui/core/Link';

/**
 * Change the content to add your own bio
 */

export default () => (
  <Fragment>
    <Styled.a as={Link} to="/">Gan0803</Styled.a>
    <br />
    ソフトウェアエンジニア
    <br />
    Androidやってます。趣味は宇宙開発です。
    <br />
    <ExtLink href="https://twitter.com/Gan0803" target="_blank" rel="noopener noreferrer" >
      <TwitterIcon style={{ maxWidth: 26, fontSize: 26, margin: 10, color: "#1DA1F2" }} />
    </ExtLink>
    <ExtLink href="https://github.com/Gan0803" target="_blank" rel="noopener noreferrer">
      <GitHubIcon style={{ maxWidth: 26, fontSize: 26 }} sx={{ margin: 10, color: 'github' }} />
    </ExtLink>
  </Fragment>
)

これでcolor modeに応じてアイコンの色を変えることができました。例はこのブログのbiographyにあるGitHubアイコンを見てみてください。