コンテンツにスキップ

SSE トースト

sse-toastサーバ起点の通知のための公認パターンです: サーバが JSON ペイロードつきの名前付き SSE イベントをプッシュし、1 つの隠れた ブリッジ要素がそれを DOM の CustomEvent に変えます — そのため既存の トースト契約と データ領域の無効化 契約は、HX-Trigger 起点のときとまったく同じに、ただしリクエスト なしで機能します。 マークアップのバージョニングポリシーの 下で安定しています。

必要なのは installSseDispatch()installToast()(どちらも自動 初期化の ./behaviors バンドルに同梱)、加えて SSE 拡張です。

ストリームは約 15 秒のスクリプト済みシーケンスを一度だけ再生し、 data-sse-close に名指しされた demo:done イベントで自ら閉じます: 固定表示の Build #42 started トーストがその場で finished に更新され (id による更新パターン)、items:changed のプッシュで下の領域が 再取得され(Rendered at の時刻に注目)、閉じる前に最後の info トーストが届きます。シーケンスはページ読み込み時に始まります — 終わってしまっていたら Replay the stream が新しいスコープ (新しい EventSource)をスワップして再実行します。

A scripted ~15 s sequence — two toasts, an update, a region refresh.

Items

<div data-hx-ext="sse" data-sse-connect="/events">
<span hidden data-hc-sse-dispatch
data-sse-swap="hc:toast, items:changed"></span>
</div>

ブリッジは決して描画されず、フォーカスも受け取りません。その data-sse-swap に名指しされた各 SSE イベントについて、 installSseDispatch() はスワップをキャンセルし、代わりにバブリング する CustomEvent を発火します — SSE のイベント名が DOM のイベント名に なり、JSON ペイロードが detail になります。

event: hc:toast
data: {"message":"Build #42 finished","variant":"success"}
event: items:changed
data: {}
  • hc:toast のペイロードはトーストの detail の形そのままです: message(必須)、titlevariantdurationidaction。 サーバプッシュの進捗には id による更新パターンが使えます — 同じ id のイベントを繰り返すと 1 つのトーストがその場で更新されます (loading → success)。
  • ドメインイベントは通常 {} です: data-hx-trigger="items:changed from:body" で待ち受けている データ領域が自分を再取得します。サーバがプッシュするのは無効化 で、領域が再描画をプルします — プッシュは小さいまま、再描画は 冪等のまま、再接続の欠落は次のイベントで自己修復します。
data:結果
空 / なし発火される。detail = {}
JSON オブジェクト発火される。そのオブジェクトが detail
それ以外(配列、文字列、数値、不正な JSON)破棄 — スワップはキャンセルされたまま、何も発火されない

マークアップが許可リストです。 ページが data-sse-swap に列挙した イベント名だけが発火可能です — サーバは、ページが宣言していない DOM イベント名を勝手に作れません。ペイロードは不活性な CustomEvent.detail データです: マークアップになることも、評価される こともありません。

トーストビヘイビアのセマンティクスはそのまま適用されます — variant: "error"role="alert"(assertive)、それ以外は role="status"(polite)で描画されます。サーバプッシュのトーストは ユーザーの操作なしに届くため、polite なバリアントを選び、error は 割り込む価値のある中断のために取っておいてください。ユーザーが 見逃してはならない状態は、一時的なトーストだけでなくページの中 (sse-updates の領域)に 置くべきです。

ペイロードのルールと領域無効化の合成は、実 EventSource の ブラウザテスト(test-browser/sse.spec.mjs)で固定されています。