コンテンツにスキップ

トグルグループ

hc-toggle-group は連結されたトグルボタンの列で、shadcn の ToggleGroup に相当します。2 つの選択モードがあり、キーボードと状態の ロジックのための小さなビヘイビア(installToggleGroup)を同梱します。 CSS はセグメンテッドコントロールのスキンです。

モードはグループの data-type で設定し、ボタン上の ARIA role に反映 されます — セマンティクスに一致するマークアップを選んでください。

別名: セグメンテッドコントロール。

同時にオンにできるボタンは 1 つだけです。 WAI-ARIA APG に従い、 排他的なトグルの集合は、見た目がボタンでもラジオグループです: グループに role="radiogroup"、各ボタンに role="radio" + aria-checked を使います。選択はフォーカスに追従し(矢印キーが移動 かつ選択)、クリックでグループが空になることはありません。

各ボタンが独立に切り替わります。グループに role="group"、各ボタンに aria-pressed を使います。矢印キーはフォーカスを動かし、Space / Enter / クリックがフォーカス中のボタンをオン / オフします。

グループの data-sizesmmd(デフォルト)、lg を受け付け、 共有の --hc-control-* スケールから値を取ります(そのため data-density が一貫して縮めます)。

キーSingle(ラジオ)Multiple(グループ)
Tabグループへ入る / 出る(1 ストップ)。同じ。
/ 次へフォーカス移動 + 選択。次へフォーカス移動。
/ 前へフォーカス移動 + 選択。前へフォーカス移動。
Home / End最初 / 最後の有効なボタン + 選択。最初 / 最後の有効なボタン。
Space / Enterフォーカス中のボタンを選択。フォーカス中のボタンをトグル。

ナビゲーションは両端でラップし、無効なボタン(disabled または aria-disabled="true")をスキップします。グループはロービングタブ インデックスによる単一の Tab ストップです。

import { installToggleGroup } from '@hypermedia-components/core';
installToggleGroup(); // idempotent; returns an uninstaller

ゼロ設定の @hypermedia-components/core/behaviors エントリは自動で インストールし、htmx でスワップされた内容も自動で拾います。すべての 変更はグループ上でバブリングする hc:togglegroupchange を発火します:

group.addEventListener('hc:togglegroupchange', (e) => {
// single → { type:'single', value, item, group }
// multiple → { type:'multiple', values, item, pressed, group }
console.log(e.detail);
});

value / values は各ボタンの data-value 属性から来ます。

グループに data-name="X" を設定すると、ビヘイビアが隠し input を 維持し、ネイティブコントロールのようにシリアライズされます — チェック済みの値に 1 つの <input type="hidden" name="X">(single)、 または押されている値ごとに 1 つ(multiple)。サーバ側に JS の配線は 不要です。

<div class="hc-toggle-group" role="radiogroup" data-type="single"
data-name="view" aria-label="View">
<button type="button" class="hc-toggle" role="radio"
aria-checked="true" data-value="grid">Grid</button>
<button type="button" class="hc-toggle" role="radio"
aria-checked="false" data-value="list">List</button>
</div>
<!-- submits view=grid -->

変更イベントから直接リクエストを駆動できます — 例: 領域をスワップする セグメント型ビュー切り替え:

<div class="hc-toggle-group" role="radiogroup" data-type="single"
aria-label="View"
data-hx-get="/reports"
data-hx-trigger="hc:togglegroupchange"
data-hx-include="this"
data-hx-target="#report"
data-name="range">
<button type="button" class="hc-toggle" role="radio" aria-checked="true" data-value="7d">7d</button>
<button type="button" class="hc-toggle" role="radio" aria-checked="false" data-value="30d">30d</button>
<button type="button" class="hc-toggle" role="radio" aria-checked="false" data-value="90d">90d</button>
</div>

data-hx-include="this"data-name 統合の書く隠し input を拾う ため、リクエストは range=7d などを運びます。

選択をインラインで反映します(detail は single なら value、 multiple なら values を運びます):

<div class="hc-toggle-group" role="radiogroup" data-type="single" aria-label="View"
_="on hc:togglegroupchange add .is-{event.detail.value} to #grid">
</div>

さらなるパターン: Hyperscript → コンポーネントイベントへの反応

  • グループに aria-label(または aria-labelledby)でアクセシブルな 名前を与えてください。
  • セマンティクスに一致する role を選んでください: 排他的な選択は 独立したトグルの集合ではなくラジオグループです。排他的な選択に aria-pressed を使うと、スクリーンリーダーの利用者に複数同時オンが 可能だと誤解させます。
  • ビヘイビアが aria-checked / aria-pressed とロービングタブ インデックスを同期し続けます。マークアップで設定するのは初期状態 だけです。
  • 無効なボタンはキーボードナビゲーションからスキップされます。

component トークン(component.tokens.json):

トークンパス用途
toggle.height / padding-x / radius / font-size / font-weightボックスの寸法(height と padding-x は密度対応)。
toggle.fg / bg / border平常時の色。
toggle.hover-bg / hover-fgホバー状態。
toggle.on-bg / on-fg / on-border選択 / 押下状態 — アクセントは data-color に追従。
toggle.disabled-fg / disabled-bg無効状態。
toggle.sm.* / lg.*サイズバリアント。
生成される CSS 変数を表示
--hc-toggle-height | -padding-x | -radius | -font-size | -font-weight
--hc-toggle-fg | -bg | -border
--hc-toggle-hover-bg | -hover-fg
--hc-toggle-on-bg | -on-fg | -on-border
--hc-toggle-disabled-fg | -disabled-bg
--hc-toggle-sm-* | -lg-*
  • ボタン — 持続的な状態 ではなく単発のアクションに。
  • タブ — 各オプションが 異なるコンテンツパネルを表示するとき。
  • スイッチ — 単一の オン / オフ設定に。