カラーコードをコピペできるカラーピッカー（Rails部分テンプレート＋Stimulus）

標準の`<input type="color">` カラーピッカーは便利ですが、選んだカラーコードを直接コピペできないのが地味に不便…😢

「カラーコードをコピペできるカラーピッカーが欲しい！」と思い、Railsの部分テンプレート＋Stimulus.jsで作ってみました。

## 📋 背景
Railsで`color_field` を使うと、

```erb
<%= form.color_field :color_field %>
```

このようなHTMLが生成されます。

```html
<input value="#000000" type="color" name="color_sample[color_field]" id="color_sample_color_field">
```


![CleanShot 2025-06-08 at 10.13.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128429/a65ca904-7085-4acd-94b9-4f27be87be3e.png)

このHTML標準のカラーピッカーだと、選択したカラーコードをコピペできません...


## 🎛️ 動作イメージ

- カラーピッカーで色を選択すると、隣のテキストボックスにも自動でカラーコード（#ff0000形式）が反映
- テキストボックスをクリックすれば全選択されるので、そのままコピペ可能
- テキストボックスを直接編集してもカラーピッカーに同期します

![CleanShot 2025-06-08 at 10.05.22.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128429/ef8dbe5c-057c-4556-9c51-d8ceecf71653.gif)

## 📦 環境

```shell
$ ruby -v
ruby 3.4.4 (2025-05-14 revision a38531fd3f) +PRISM [arm64-darwin24]

$ rails -v
Rails 8.0.2

# Stimulusのバージョン
$ grep stimulus-rails Gemfile.lock
    stimulus-rails (1.3.4)
  stimulus-rails
```

> Stimulusは stimulus-rails（バージョン1.3.4）で導入されています（rails new直後から使えます）。

## 🚀 使い方

使いまわしやすいように部分テンプレート化しています。

カラーコード入力欄を設置したい場所で下記のように呼び出せます。

```erb
<%= render 'shared/color_picker', color_code: "#ff0000", name: "your_model[color_attr]" %>
```

- `color_code`: 初期値を渡します（
- `name`: フォーム送信用のパラメータ名

## 👇 コード

### 1. 編集画面での呼び出し例

```erb
<!-- app/views/color_samples/edit.html.erb -->
<h1>ColorSamples#edit</h1>

<%= form_with(model: @color_sample, local: true) do |form| %>
  <span>カラー1</span>
  <%= render 'shared/color_picker', color_code: @color_sample.code1, name: 'color_sample[code1]' %>
  <span>カラー2</span>
  <%= render 'shared/color_picker', color_code: @color_sample.code2, name: 'color_sample[code2]' %>
  <span>カラー3</span>
  <%= render 'shared/color_picker', color_code: @color_sample.code3, name: 'color_sample[code3]' %>
  <br>
  <%= form.submit '保存' %>
<% end %>
```

- `render 'shared/color_picker', color_code: ..., name: ...` の形式で使うだけ
- モデルの値や任意のデフォルト値を`color_code`に渡す

### 2. カラーピッカー部分テンプレート

```erb
<!-- app/views/shared/_color_picker.html.erb -->

<%# カラーピッカーとテキストを横並びで配置。Stimulusで連動。 %>
<% color_code ||= "#000000" %>
<% name ||= nil %>
<div class="color-picker-wrapper" data-controller="color-picker" style="display: flex; gap: 8px; align-items: center;">
  <input type="color"
    name="<%= name %>"
    value="<%= color_code %>"
    data-color-picker-target="color"
    data-action="input->color-picker#updateFromColor"
    style="width: 36px; height: 36px;"
    aria-label="カラーピッカー">
  <input type="text"
    value="<%= color_code %>"
    data-color-picker-target="text"
    data-action="input->color-picker#updateFromText"
    style="width: 90px;"
    onclick="this.select();"
    aria-label="カラーコード">
</div>
```

- Stimulusのdata-controllerやdata-targetで連動させています

### 3. Stimulusコントローラー

```js
// app/javascript/controllers/color_picker_controller.js

import { Controller } from "@hotwired/stimulus"

// カラーピッカーとテキストを双方向に連動
export default class extends Controller {
  static targets = ["color", "text"]

  connect() {
    // 初期表示時、テキストボックスにもカラーコードをセット
    this.textTarget.value = this.colorTarget.value
  }

  // 色選択時、テキストも更新
  updateFromColor() {
    this.textTarget.value = this.colorTarget.value
  }

  // テキスト手入力時、バリデーションしてカラーも更新
  updateFromText() {
    // #ff0000 形式のみ許可
    if (/^#[0-9a-fA-F]{6}$/.test(this.textTarget.value)) {
      this.colorTarget.value = this.textTarget.value
    }
  }
}
```

- カラーピッカー・テキストボックスの値が常に同期します

## 🛠 StimulusによるUI連動のしくみ

このカラーピッカーは、Stimulus.jsというなJavaScriptフレームワークを使って、HTMLの要素同士を簡単に連動させています。

### data-controller とは？

`data-controller="color-picker"` をdivタグなどにつけることで、「この範囲には`color_picker_controller.js` を適用しますよ」 という意味になります。

Rails（stimulus-rails環境）だと、`app/javascript/controllers/color_picker_controller.js` が自動で呼び出されます。

### data-target とは？
`data-color-picker-target="color"` `data-color-picker-target="text"` という風に指定すると、Stimulusコントローラ内から

```js
this.colorTarget
this.textTarget
```
のように特定のDOM要素を簡単に参照できるようになります。
これで、「カラーピッカーinput」と「テキストinput」をそれぞれ直接操作できます。

### data-action とは？

`data-action="input->color-picker#updateFromColor"` これは、「inputイベントが発生したとき、color-pickerコントローラの`updateFromColor`メソッドを呼ぶ」という意味です。

テキストボックス側は`data-action="input->color-picker#updateFromText"` として、手入力時にもJS側の処理を自動で呼び出します。



## まとめ

- この部分テンプレートをrenderするだけで、どこでもコピペできるカラーピッカーUIが手軽に設置できます
- カラーコードのコピペ・編集・連動がワンストップで実現できて便利です

## 🔗参考
Stimulus Handbook
https://chatgpt.com/c/6844cab6-965c-800f-b570-8a02ac262f38#:~:text=Stimulus-,Handbook,-Rails%E3%82%AC%E3%82%A4%E3%83%89%20%E9%83%A8%E5%88%86

Railsガイド 部分テンプレート
https://chatgpt.com/c/6844cab6-965c-800f-b570-8a02ac262f38#:~:text=Rails%E3%82%AC%E3%82%A4%E3%83%89-,%E9%83%A8%E5%88%86,-%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88