明日の自分のために

moon indicating dark mode
sun indicating light mode

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

June 11, 2020

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アイコンを見てみてください。