Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般
  • Ruby / Rails関連

Railsの技: StimulusJSで使えるキーボードショートカットのライブラリ(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

Railsの技: StimulusJSで使えるキーボードショートカットのライブラリ(翻訳)

本記事は、Boring Railsの新シーズンコンテンツ「Hotwire Summer」の一部です。

キーボードショートカットは、Webアプリケーションのユーザーエクスペリエンスを高めて使い勝手を改善する優れた方法のひとつです。ホットキーの使いこなし方を知らない人にとっても、たとえばescキーを押すとモーダルダイアログを閉じられるといった小さな心配りひとつが、アプリケーションの印象に大きく影響することもあります。

Stimulusにはデフォルトのホットキー機能が組み込まれていません。私が最近手掛けたArrows.toプロジェクトの一環として評価を行ったホットキーのエコシステムについて、私の考えを共有したいと思います。

1. stimulus-hotkeysパッケージ

leastbad/stimulus-hotkeys - GitHub

stimulus-hotkeysパッケージはhotkeysコントローラを提供し、JSONオブジェクトを用いてキーボードショートカットをStimulusアクションにマッピングします。

<div
  data-controller="hotkeys"
  data-hotkeys-bindings-value='{"ctrl+z, command+z": "#foo->editor#undo"}'
></div>

<div id="foo" data-controller="editor"></div>

bindingsマップの構文はStimulusアクションの構文と似ていますが、Stimulusコントローラを探索してアクションを呼び出すためにselectorを追加します。内部では、stimulus-hotkeysがより一般性の高いHotKeys.JSライブラリを使っているので、あらゆるキーの組み合わせ、モディファイアキー、スコープをサポートしています。

私がこのライブラリで気に入った点は、ショートカットのマッピングをHTMLマークアップ内に記述することです。これはHotwireの精神を強く感じさせるからです。このライブラリはStimulusコントローラに余分なコードを一切追加しないので、他のサードパーティStimulusコントローラと組み合わせるときの相性も最高です。

惜しい点は、ハッシュ風のデータ構造をHTML属性に追加するので構文がトリッキーになることです。私はJSON構文が好きではありません。

2. stimulus-use/useHotkeys

stimulus-use/stimulus-use - GitHub

stimulus-useプロジェクトは、Stimulus向けの再利用可能な振る舞いのコレクションです。Reactに親しんでいる人なら、Reactのhooksシステムに似たものをこのプロジェクトに感じるかもしれませんが、Stimulus向けである点が異なります。

このコレクションにはuseHotkeysも含まれています。stimulus-hotkeysと同様に、重たい仕事はHotKeys.JSが行ってくれます。

こちらは、必要なホットキーとそれに対応するハンドラを以下のように自分のStimulusコントローラ内に定義する必要があります。

import { Controller } from '@hotwired/stimulus'
import { useHotkeys } from 'stimulus-use'

export default class extends Controller {
  connect() {
    useHotkeys(this, {
      'cmd+t': [this.openPalette],
      '.': [this.editFile]
    })
  }
}

このライブラリはStimulusコントローラに置くのにうってつけで、コントローラが切断されたときにショートカットの登録を自動的に解除してくれます。どんなホットキーを設定しているかがひと目でわかるので、自分のアプリケーションコントローラにホットキーを追加するオプションとしてよくできていると感じられました。

ただ私たちのニーズではひとつ惜しい点がありました。私たちはページに常駐するコントローラを使っているのですが、非表示の場合はホットキーが効かないようにする必要があったのです。useHotKeyはStimulusコントローラのライフサイクルを扱いますが、キーボードイベントを動的にバインドしたりバインド解除したりしようとするときの柔軟性に欠けます。

3. HotKeys.JSを直接使う

Stimulusに特化した人気のソリューション2つを調べた結果、どちらも同じHotKeys.jsに依存していることがわかったので、HotKeys.jsのソースをストレートに使うことに決めました。

import { Controller } from '@hotwired/stimulus'
import hotkeys from 'hotkeys-js'

export default class extends Controller {
  connect() {
    hotkeys("esc", () => this.doSomething())
  }

  disconnect() {
    hotkeys.unbind("esc")
  }
}

このライブラリを直接追加するのは簡単ですが、必ずunbindを呼び出してイベントを明示的にクリーンアップする必要がある点に注意してください。さもないとホットキー関数のインスタンスが複数作成されてしまいます。

基本的なホットキーを1個か2個追加する程度のシンプルなケースであれば、このアプローチは完璧に有効です。私たちのアプリケーションではショートカットのバインドやバインド解除を細かく制御する必要があったので、最終的にこのソリューションに落ち着きました。

4. github/hotkey

github/hotkey - GitHub

私が評価を行った最後のオプションは、GitHubのhotkeyという小さなライブラリです。これはStimulusやHotwireだけに特化したものではありません。

<button data-hotkey="Shift+?">Show help dialog</button>

<a href="/page/2" data-hotkey="j">Next</a>
<a href="/help" data-hotkey="Control+h">Help</a>
<a href="/rails/rails" data-hotkey="g c">Code</a>
<a href="/search" data-hotkey="s,/">Search</a>

私はBasecampが運営するHEY.comのsourcemapでこのライブラリを見つけ、GitHubのメインRailsアプリで実地のバトルテストを経ていることを知りました。同READMEには「GitHubのほぼすべてのページで使われている」と書かれています。

このライブラリのdata-hotkey属性は、今回紹介する4つのオプションの中で最も構文がすっきりしています。ライブサイクルイベントを扱うためにStimulusコントローラのラッパーが必要ですが、installuninstallを呼び出すぐらいにしか使いません。

このライブラリの設計はブラウザのデフォルトの振る舞いに強く依存しています。任意のJavaScriptやStimulusアクションを呼び出す代わりに、github/hotkeyがターゲットとなるHTML要素のアクションをトリガーします(ターゲットがリンクならリンク先を開く、ボタンなら送信する、入力フィールドならフォーカスを置くなど)。

ブラウザのネイティブ機能を利用する形で自分のマークアップを構成できるのであれば、このライブラリはよいオプションのひとつです。ただし、既存のStimulusに直接フックをかける方法はありません。

まとめ

どのライブラリを選択するかは、ホットキーで何が必要かによって変わります。

stimulus-hotkeys
追加するだけで利用でき、JavaScriptコードの追加が一切不要
stimulus-use/useHotKeys
StimulusネイティブのHotKey.js APIラッパーとして使うのに便利
HotKey.js
強力なキーイベント抽象化を自分のコードにミックスイン可能
github/hotkey
ブラウザネイティブの振る舞いに強く依存するが、構文は最高

最終的には、自分が作りたいものとのトレードオフを見極める必要があります。私はHotKey.jsを直接使うことにしましたが、これが要件に最も見合っていたからです。


本記事が役に立つと思った方は、ぜひフォームでニュースレターの登録をお願いします。余分な文章を削ぎ落とした読みやすく価値ある情報だけをニュースレターで配信いたします。

関連記事

Railsの技: “プログレッシブエンハンスメント”でHotwire的思考を身につける(翻訳)

Better Stimulusガイド:アーキテクチャ1: アプリケーションコントローラ(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。