4 ポイント 投稿者 GN⁺ 2025-03-08 | 1件のコメント | WhatsAppで共有
  • ボタンは動的なWebアプリケーションを作るうえで不可欠。メニューを開いたり、操作を切り替えたり、フォームを送信したりするために使われる
  • Chrome 135では、新しい command および commandfor 属性によって、従来の popovertargetaction および popovertarget 属性を改善し、置き換える
  • 既存のボタン動作を実装する際に発生する問題点:
    • HTMLの onclick ハンドラは、セキュリティポリシー(CSP)のため実際のコードでは利用が制限されることがある
    • ボタンと他の要素の状態同期が必要で、アクセシビリティを保ちながら状態を管理するコードは複雑
    • React、AlpineJS、Svelte などでも状態管理とイベント処理は複雑

commandcommandfor パターン

  • commandcommandfor 属性を使うと、ボタンが他の要素に対して宣言的に動作できる。これはフレームワークの利便性を提供しつつ柔軟性も維持する
  • commandfor ボタンはIDを使い(for 属性に近い)、command は組み込み値を受け取って、より直感的なアプローチを提供する
  • 例: メニューを開くボタンの実装
    • aria-expanded や追加のJavaScriptは不要
    
      Open Menu
    
    

commandcommandfor vs popovertargetactionpopovertarget

  • popover を使ったことがあれば、popovertargetpopovertargetaction 属性に見覚えがあるかもしれない
  • これらは commandforcommand に似た動作をするが、ポップオーバー専用
  • 新しい属性は従来の属性を完全に置き換え、追加機能も提供する

組み込みコマンド

  • command 属性には、さまざまなAPIに対応する動作が組み込まれている
    • show-popover: el.showPopover() に対応
    • hide-popover: el.hidePopover() に対応
    • toggle-popover: el.togglePopover() に対応
    • show-modal: dialogEl.showModal() に対応
    • close: dialogEl.close() に対応
  • 例: 削除確認ダイアログの実装
    • JavaScriptなしで状態管理とアクセシビリティ対応が可能
    
      Delete Record
    
        Delete Record?
    
      Are you sure? This action cannot be undone
    
          Cancel
    
          Delete
    
    
    • 結果処理コード: ダイアログの 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" イベントを発火するが、それ以外の追加ロジックは実行しない
  • 例: 画像回転コマンドの実装
    
      Landscape
    
      Portrait
    
      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";
        }
      });
    
    

Shadow DOMでのコマンド処理

  • Shadow DOMでは commandfor がIDベースで動作するため、次のような制限がある:
    • Shadow DOM間で要素を参照できない
    • この場合、JavaScript APIを使って .commandForElement プロパティを設定できる
  • 例: Shadow DOMでのコマンド接続
    
        Show popover
    
      customElements.define("my-element", class extends HTMLElement {
        connectedCallback() {
          const popover = this.querySelector('[popover]');
          this.shadowRoot.querySelector('button').commandForElement = popover;
        }
      });
    
    

今後の計画

  • Chromeでは、さらに多くの組み込みコマンドの導入を計画している:
    • `` 要素の開閉
    • および での "show-picker" コマンド対応
    • および の再生命令
    • 要素内テキストのコピー機能

1件のコメント

 
GN⁺ 2025-03-08
Hacker Newsの意見
  • プログラミング言語理論家たちは80年代から、"goto"のより強力なバージョンである"comefrom"について推測してきた。これはintercalでのみ実装されていた。intercalはCのような言語よりも安全性、性能、人間工学の面で優れているが、商業市場への参入には苦労している。javascriptがintercalのこの機能を統合するのを見るのは興味深い。これが、javascriptのクロージャベースのオブジェクトが関数型プログラミングを主流へ導いたように、礼儀正しいプログラミングの急増につながることを願う

  • InvokersはChromeだけのものではない。Firefox nightlyでもすでに利用可能

  • JSなしで宣言的なUI動作を実装するというアイデアは魅力的

    • ポップオーバー/モーダルのボイラープレートを削減する(aria-expandedの操作が不要)
    • show-modalのような組み込みコマンドはアクセシビリティをマークアップに統合する
    • カスタムコマンド(例: --rotate-landscape)により、コンポーネントはHTMLを通じてAPIを公開できる
  • 疑問点:

    • 抽象化 vs. マジック: これは単に複雑さをJSからHTMLへ移しているだけなのか? フレームワークはすでに状態を抽象化している。これはどう共存するのか?
    • Shadow DOMとの摩擦: shadow roots間で.commandForElementを設定するにはJSが必要。これは半分しか解決されていない問題のように見える
    • 将来性: OpenUIが20個以上のコマンド(例: show-picker, toggle-details)を追加した場合、プラットフォームはニッチな構文で膨れ上がるのか?
  • 仕様:

    • button element, commandfor属性
    • button element, command属性
  • これはNext、Be、Appleなどが約30年前に使っていたアクション/メッセージングパターンなのか、それとも私が何か見落としているのか

    • これは有用だったが、基本的なデザインパターンを維持しようとする複雑さのため、インターフェースベースのコントローラーパターンへと進化した。したがって、この箱が開くなら多くの改善要望が出ると予想する
  • Netscapeの初期のJava UIツールキット(IFC)はアクション要素を接続できた

  • 新しいcommandおよびcommandfor属性はpopovertargetactionおよびpopovertarget属性を改善し、置き換える

    • これらは基本的に利用可能になったのか? 置き換えるとはどういう意味か? いずれこれを削除するのか? ウェブ開発者は、もはや不要になったものをアップデートで削除することはできない
  • 文字列でプログラミングすることに完全にアレルギー反応がある。アクセシビリティ上の利点は理解するが、別のWebアプリ動作レイヤーとして要素IDを使うことには特に興味をひかれない

  • 完全なAPIなしにこれを実装すべきではなかった。5個ほどのコマンドではなく、HTMLを通じてあらゆるJavaScript機能を実装できるように見える。そうなると数千のコマンドになり得る

  • HTMLでcommand and conquerに期待していた

  • HTMLを改善し拡張するのは良いことだが、まだ道のりは長い。HTMXチームはいくつか良いアイデアを持っている