Reactで作る独自カラーピッカー

# Reactで作る独自カラーピッカー

# `<input type="color">`

`<input type="color">`を使うと以下の画像のように簡単に色選択のinputを作ることができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188172/c205dae8-f519-3467-dfb9-701f0feae0b1.png" width="200" alt="Chrome Color Picker" />

しかし`<input type="color">`では各プラットフォームによって表示されるカラーピッカーが異なり、一部のプラットフォームでは機能が貧弱であるという欠点があります。例えば、プラットフォームごとに以下の図のように異なるカラーピッカーが表示されますがAndroidは貧弱なUIになっています。

![OS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188172/e04156c6-6715-1525-9eec-24b910bb2cba.png)

色入力が稀な場合など`<input type="color">`で十分な場合も多いですが、プロダクトによっては色を選択が重要になることもあります。この記事ではそういった場合に必要になる独自カラーピッカーのReactでの作例を紹介します。

# `<input type="color">` vs 独自カラーピッカー

独自カラーピッカーについて述べる前に`<input type="color">`と独自カラーピッカーどちらを使うべきか、メリットデメリットを整理しておきます。

- `<input type="color">`
	- メリット
		- 実装が楽
		- OSに適したUIが表示される
		- ブラウザのプログレッシブエンハンスメントの恩恵を受けられる
		- ブラウザのアクセシビリティ支援の恩恵を受けられる
	- デメリット
		- カラーピッカーが貧弱なプラットフォームもある
- 独自カラーピッカー
	- メリット
		- 多様なピッカーを提供できる
		- プラットフォーム共通の体験を提供できる
	- デメリット
		- 実装が手間
		- ブラウザのプログレッシブエンハンスメントの恩恵を受けられない
		- ブラウザのアクセシビリティ支援の恩恵を受けられない
		- 各プラットフォームにデザインを最適化するのに手間がかかる

メリット/デメリットを比較した時、どちらを選ぶかはサービスの規模や会社によって変わると思われます。例えば、モイでは`<input type="color">`をできる限り使うのが良いと思っています。理由としてはフロントエンドエンジニアの数が少なくバックエンドのエンジニアもhtmlを書くこともあるので書き方がバラつかず、かつプログレッシブエンハンスメントの恩恵が期待できることが魅力的だからからです。

### 補足：プログレッシブエンハンスメント

プログレッシブエンハンスメントは、平たく言うと古い環境でも最低限の機能使えるようにするが新しい環境ならよりリッチな機能が使えるようにするという考え方です。例えば、iOSの色選択UIはiOS15で大きく進化しました。もし`<input type="color">`を使っていればサービスは何もしなくとも自動でより便利なUIが使えるようになります。アクセシビリティ支援についても同じようにOSのバージョンアップにより進化することもあるでしょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188172/0063357b-6f7e-5a3a-6c09-1b679247741e.png" width="400" alt="プログレッシブエンハンスメント" />


# 独自カラーピッカー

さて、今回は色選択が重要なプロダクトのために開発することになりReactで独自カラーピッカーを実装することになりました。すでに[React Color](https://casesandberg.github.io/react-color/)などのライブラリがあるのも関わらず、独自で作ることにしたことには以下の理由がありました。

- ライブラリに用意されているデザインがPC/スマホの両用に耐えない
- ライブラリのサイズが大きい
- よりUIをカスタマイズしたい

これらを踏まえつつ、実装するカラーピッカーのデザインはiOSのカラーピッカーをリファレンスとしました。iOSのカラーピッカーは出来が良く、デフォルトはグリッドから色を選ぶことができます。また、パラメータとスライダーを使って細かく色を作ることができるUIになっています。

![iOS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188172/777dbd7c-254f-27f8-3ef0-4f25784b2d0f.png)

### 補足：PCのカラーピッカー、スマホのカラーピッカー

PC/スマホで特性が異なるので理想的にはプラットフォームごとにUIを分けるのがベストだと思われます。PCユーザーはマウスで正確な操作が可能でリテラシーや年齢の高いユーザーが多いので高度なカラーピッカーを提供するだけで問題ない可能性が高いでしょう。一方、スマホではタッチを使うので正確な操作が難しいです。また、初心者から上級者までとPCより幅広いユーザーがいることが予想されます。そのため、ヒットテストを大きめにしたり、プリセットやおすすめの色など初心者向けの機能が提供されることが望ましいと思われます。

**PCのカラーピッカー**

![OtherApp2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188172/f18c6dc7-f415-5a71-d12e-99eb907243fe.png)

**スマホのカラーピッカー**

![OtherApp1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188172/a12b9432-1505-54db-5b92-9e74ac801c38.png)

今回はPC/スマホ両方のデザインを保守するほどの人的リソースがないので、どちらでも使えるものを目指すことにしました。

# 作例（サンプルコード）

最低限の実装のサンプルコードを示しました。コード的に特筆すべきところはありません。パラメーターでの色選択はサイズが小さいライブラリを利用しています。また、グリッドでの色選択はiOSのカラーピッカーと同じしています。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="RwvOPLB" data-user="Takuto-Yoshikawa" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/Takuto-Yoshikawa/pen/RwvOPLB">
  Color Picker</a> by Takuto Yoshikawa (<a href="https://codepen.io/Takuto-Yoshikawa">@Takuto-Yoshikawa</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 実際の例：ツイキャス デザインスタジオ

最後に私がUXデザイン/UIデザイン/フロントエンド実装/バックエンド実装を担当している[デザインスタジオ](https://studio.twitcasting.tv/)での例を紹介します。このシステムはスマホ/PCでOBSのような配信画面が作れるものです。[この動画](https://www.youtube.com/watch?v=vTHZtlRGT_U)を見るとイメージが掴めるかと思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188172/f13c8892-48b8-cd5a-baa5-4338d9729ec8.png" width="375" alt="デザインスタジオ" />

この例ではサンプルコードにはない最近使った色機能や色コード
での指定機能が実装されています。また、高さを抑えることで色変更の対象を見ながら色を変えることができるようになりました。これは`<input type="color">`を利用する場合はスマホでは実現できない動作で操作性の大幅な改善が可能になりました。

# 今後やりたいこと

今回は実装していませんが以下のような機能を実装するとより便利になるだろうと考えています。

- グリッドで複数のプリセットを提供する
- スライダーをHSB指定に対応させる

# まとめ

- `<input type="color">`、独自カラーピッカーのメリット/デメリットや使い分けを述べた
- 独自カラーピッカーの作例と実例を紹介した