Chrome 135でボタンに `command` と `commandfor` を導入
(developer.chrome.com)- ボタンは動的なWebアプリケーションを作るうえで不可欠。メニューを開いたり、操作を切り替えたり、フォームを送信したりするために使われる
- Chrome 135では、新しい
commandおよびcommandfor属性によって、従来のpopovertargetactionおよびpopovertarget属性を改善し、置き換える - 既存のボタン動作を実装する際に発生する問題点:
- HTMLの
onclickハンドラは、セキュリティポリシー(CSP)のため実際のコードでは利用が制限されることがある - ボタンと他の要素の状態同期が必要で、アクセシビリティを保ちながら状態を管理するコードは複雑
- React、AlpineJS、Svelte などでも状態管理とイベント処理は複雑
- HTMLの
command と commandfor パターン
commandとcommandfor属性を使うと、ボタンが他の要素に対して宣言的に動作できる。これはフレームワークの利便性を提供しつつ柔軟性も維持するcommandforボタンはIDを使い(for属性に近い)、commandは組み込み値を受け取って、より直感的なアプローチを提供する- 例: メニューを開くボタンの実装
aria-expandedや追加のJavaScriptは不要
<button commandfor="my-menu" command="show-popover"> Open Menu </button> <div popover id="my-menu"> <!-- ... --> </div>
command と commandfor vs popovertargetaction と popovertarget
popoverを使ったことがあれば、popovertargetとpopovertargetaction属性に見覚えがあるかもしれない- これらは
commandforとcommandに似た動作をするが、ポップオーバー専用 - 新しい属性は従来の属性を完全に置き換え、追加機能も提供する
組み込みコマンド
command属性には、さまざまなAPIに対応する動作が組み込まれているshow-popover:el.showPopover()に対応hide-popover:el.hidePopover()に対応toggle-popover:el.togglePopover()に対応show-modal:dialogEl.showModal()に対応close:dialogEl.close()に対応
- 例: 削除確認ダイアログの実装
- JavaScriptなしで状態管理とアクセシビリティ対応が可能
<button commandfor="confirm-dialog" command="show-modal"> Delete Record </button> <dialog id="confirm-dialog"> <header> <h1>Delete Record?</h1> <button commandfor="confirm-dialog" command="close" aria-label="Close"> <img role="none" src="/close-icon.svg"> </button> </header> <p>Are you sure? This action cannot be undone</p> <footer> <button commandfor="confirm-dialog" command="close" value="cancel"> Cancel </button> <button commandfor="confirm-dialog" command="close" value="delete"> Delete </button> </footer> </dialog>- 結果処理コード: ダイアログの
closeイベントで戻り値を処理できる
dialog.addEventListener("close", (event) => { if (event.target.returnValue === "cancel") { console.log("Cancel was clicked"); } else if (event.target.returnValue === "delete") { console.log("Delete was clicked"); } });
カスタムコマンド
- 組み込みコマンド以外にも、
--接頭辞を使ってカスタムコマンドを定義できる - カスタムコマンドは対象要素で
"command"イベントを発火するが、それ以外の追加ロジックは実行しない - 例: 画像回転コマンドの実装
<button commandfor="the-image" command="--rotate-landscape"> Landscape </button> <button commandfor="the-image" command="--rotate-portrait"> Portrait </button> <img id="the-image" src="photo.jpg"> <script type="module"> const image = document.getElementById("the-image"); image.addEventListener("command", (event) => { if (event.command === "--rotate-landscape") { image.style.rotate = "-90deg"; } else if (event.command === "--rotate-portrait") { image.style.rotate = "0deg"; } }); </script>
Shadow DOMでのコマンド処理
- Shadow DOMでは
commandforがIDベースで動作するため、次のような制限がある:- Shadow DOM間で要素を参照できない
- この場合、JavaScript APIを使って
.commandForElementプロパティを設定できる
- 例: Shadow DOMでのコマンド接続
<my-element> <template shadowrootmode="open"> <button command="show-popover">Show popover</button> <slot></slot> </template> <div popover><!-- ... --></div> </my-element> <script> customElements.define("my-element", class extends HTMLElement { connectedCallback() { const popover = this.querySelector('[popover]'); this.shadowRoot.querySelector('button').commandForElement = popover; } }); </script>
今後の計画
- Chromeでは、さらに多くの組み込みコマンドの導入を計画している:
<details>要素の開閉<input>および<select>での"show-picker"コマンド対応<video>および<audio>の再生命令- 要素内テキストのコピー機能
1件のコメント
Hacker Newsの意見
プログラミング言語理論家たちは80年代から、"goto"のより強力なバージョンである"comefrom"について推測してきた。これはintercalでのみ実装されていた。intercalはCのような言語よりも安全性、性能、人間工学の面で優れているが、商業市場への参入には苦労している。javascriptがintercalのこの機能を統合するのを見るのは興味深い。これが、javascriptのクロージャベースのオブジェクトが関数型プログラミングを主流へ導いたように、礼儀正しいプログラミングの急増につながることを願う
InvokersはChromeだけのものではない。Firefox nightlyでもすでに利用可能
JSなしで宣言的なUI動作を実装するというアイデアは魅力的
疑問点:
仕様:
これはNext、Be、Appleなどが約30年前に使っていたアクション/メッセージングパターンなのか、それとも私が何か見落としているのか
Netscapeの初期のJava UIツールキット(IFC)はアクション要素を接続できた
新しいcommandおよびcommandfor属性はpopovertargetactionおよびpopovertarget属性を改善し、置き換える
文字列でプログラミングすることに完全にアレルギー反応がある。アクセシビリティ上の利点は理解するが、別のWebアプリ動作レイヤーとして要素IDを使うことには特に興味をひかれない
完全なAPIなしにこれを実装すべきではなかった。5個ほどのコマンドではなく、HTMLを通じてあらゆるJavaScript機能を実装できるように見える。そうなると数千のコマンドになり得る
HTMLでcommand and conquerに期待していた
HTMLを改善し拡張するのは良いことだが、まだ道のりは長い。HTMXチームはいくつか良いアイデアを持っている