Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Railsフロントエンド: ホットキーをStimulusで追加する(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

Railsフロントエンド: ホットキーをStimulusで追加する(翻訳)

アプリが育ってくると画面数も増えてきます。今のうちに、ユーザーがアプリ内を移動する別の方法も追加しておくことを検討しましょう。今回はキーボードショートカット(ホットキー)を導入します。

ホットキー(hotkey)による移動とは、ユーザーがマウスクリックしなくても(Web)アプリの画面上を素早く移動して操作する、キーボードショートカットの実装を指します。

幸い、ホットキーをRailsアプリに追加できるライブラリは山ほどありますが、私が自分の全Railsアプリで使い倒しているのはGitHubのホットキーです。このライブラリは軽量で使いやすく、依存関係もなく、Stimulusとの相性もバツグンなので、ここで使うのにうってつけです。

github/hotkey - GitHub

GitHubホットキーライブラリのしくみ

このライブラリは、シンプルなソリューションとして実によくできています。READMEのコードを引用してみましょう。HTMLは以下のようになります。

<a href="/" data-hotkey="g h">Home</a>

JavaScriptコードは以下のようになります。

import {install} from '@github/hotkey'

// ページにすべてのホットキーをインストールする
for (const el of document.querySelectorAll('[data-hotkey]')) {
  install(el)
}

JavaScriptの初期化が必要ですが、これでdata-hotkey属性を持つすべての要素がホットキーに対応します。これはホットですね!

このスニペットは、gキーを押してからhキーを押すとroot(/)パスにリダイレクトします。また、Shift+?キーのようにキーの組み合わせも可能です。

🔗 Stimulusコントローラを使う方法

上のコードは非常にすっきりしていますが、私はStimulusを使うのが好みです。Stimulusは、間接的なコードを減らしてコードをもう少し明示的にできる優れた方法のひとつです。

さて、Stimulusで書いたコードはどんな感じになるでしょうか?実はわずか数行に収まります。以下の手順を実行するときは、node.js(esbuildかbun)またはimportmapで@github/hotkeyライブラリを有効にしておいてください。以下はnode.jsの場合です。

import { Controller } from "@hotwired/stimulus";
import { install, uninstall } from "@github/hotkey";

export default class extends Controller {
  connect() {
    install(this.element);
  }
}

今度は以下のHTMLを使います。

<a href="/" data-controller="hotkey" data-hotkey="g h">Home</a>

今度のHTMLは最初のものより少しだけ冗長になっている点にご注目ください。このdata-controller="hotkey"属性はStimulusで動かすのに必要ですが、これはStimulus流の書き方に沿っていますし、app/javacripts/controllers/hotkey_controller.jsを探せばホットキー関連のコードが確実に見つかるので、実際にはこの書き方が優れていると私は思います。

原文お知らせ

Railsでグローバルに使えるホットキーコンポーネントやその他のUIコンポーネントをお探しの方は、Railsで初めてプロがデザインしたUIコンポーネントライブラリであるRails Designerをぜひチェックしてみてください。

🔗 リンクのリダイレクトを一工夫

Railsフロントエンド: HotwireとTailwind CSSでモーダルを作る(翻訳)

上の過去記事で紹介したモーダルを既にRailsアプリで使っていれば、同じコントローラでこれらを開くことも可能なので手間が省けます。

たとえばヘルプページを開くリンクにホットキーを追加するなら、以下のようにturbo-frame属性を正しく追加するだけで完了です。

<a href="/help/" data-controller="hotkey" data-hotkey="Shift+?" data-turbo-frame="modal">Help dialog</a>

Railsの通常のリンクで行うのと同様にdata-turbo-frame="modal"属性を追加するだけでできるので、いたってシンプルですね。

フォームを送信するときによく使われるコマンド+Enterホットキーも設定できるでしょうか?これも可能ですが、このホットキーライブラリはデフォルトではフォームの入力内でイベントを発火しないので、もうひと手間かける必要があります。ここは気をつけないと、すぐ厄介なことになるかもしれません。

必要な作業は、フォームに以下のようなhotkey-scope属性を追加することだけです。

  <form>
    <textarea name="message" id="message_content"></textarea>

    <button type="submit" data-controller="hotkey" data-hotkey="Meta+Enter" hotkey-scope="message_content">Submit</button>
  </form>

hotkey-scopeの値をtextarea要素のid(ここではmessage_content)と一致させていることにご注目ください。これで、ユーザーがMeta+Enterキーを押せばフォームが送信されます。

Railsアプリでキーボードショートカットを取得するのに必要なのは、この小さなStimulusコントローラ1つだけです(しかもコピペで使えます)。

次に検討するものがあるとすれば、コネクションを切断する方法(イベントリスナーをアンインストールしてホットキー登録を解除する)や、アクセシビリティ上の理由からユーザーごとにキーボードショートカットをオプションで無効化する方法でしょう(HotkeyライブラリのREADMEを参照)。

関連記事

Railsフロントエンド: ViewComponent+Tailwind CSS+Hotwireの便利技8つ(翻訳)

Rails: ビューをきれいに書くのに便利な知られざるヘルパー10種(翻訳)

Railsフロントエンド: フォームの.field_with_errorsスタイルを無効にする方法(翻訳)


CONTACT

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