ボタングループ
component同じ対象に対する関連した操作のボタンを横につなげ、1 つのまとまった部品に見せます。隣り合うボタンの境界線は 1 本に重なり、角丸はグループの両端だけに残ります。中身は ボタン と アイコンボタン の outline をそのまま使い、CSS だけで動きます。
基本
関連した操作を 2〜4 個つなげる。グループの中は同じ variant(outline)・theme・サイズで揃え、role="group" と aria-label で何に対する操作かを名前にする
<div class="btn-group" role="group" aria-label="テキストの編集"> <button type="button" class="btn btn-md btn-neutral btn-outline">コピー</button> <button type="button" class="btn btn-md btn-neutral btn-outline">切り取り</button> <button type="button" class="btn btn-md btn-neutral btn-outline">貼り付け</button> </div>
アイコンボタン
アイコンだけのボタンは icon-btn(outline)をつなげ、それぞれに操作名の aria-label を付ける
<div class="btn-group" role="group" aria-label="表示の拡大・縮小"> <button type="button" class="icon-btn icon-btn-md icon-btn-neutral icon-btn-outline" aria-label="縮小"> <svg class="icon icon-lg" aria-hidden="true"><use href="./icons.svg#lucide-minus"></use></svg> </button> … </div>
サイズ
中のボタンのサイズ(btn-{sm,md,lg})がそのままグループの高さになる。1 つのグループの中でサイズを混ぜない
分割ボタン
主操作の btn の右に icon-btn(chevron-down)をつなげ、アクションメニュー(.action-menu-end)でその他の操作を開く。icon-btn の aria-label に主操作の名前を含める
<div class="btn-group" role="group" aria-label="下書きの保存"> <button type="button" class="btn btn-md btn-neutral btn-outline">下書き保存</button> <button type="button" class="icon-btn icon-btn-md icon-btn-neutral icon-btn-outline" id="split-trigger" aria-label="下書き保存のその他の操作" aria-haspopup="menu" aria-expanded="false" popovertarget="split-menu"> <svg class="icon icon-lg" aria-hidden="true"><use href="./icons.svg#lucide-chevron-down"></use></svg> </button> </div> <div class="action-menu action-menu-end" id="split-menu" popover role="menu" aria-labelledby="split-trigger"> <button type="button" class="menu-item" role="menuitem" tabindex="-1">テンプレートとして保存</button> … </div>
状態
今は実行できない操作は、その 1 つだけ disabled にする(グループごと無効にしない)。フォーカス中のボタンは前面に出て、フォーカスリングが隣に隠れない(右は is-focus-preview の見本)
disabled(貼り付けるものが無い)
focus
機能
このコンポーネントの用途
同じ対象に対する関連した操作(コピー / 切り取り / 貼り付け、拡大 / 縮小 等)を 1 つのまとまりとして並べる。
選択状態を持つボタンの並び(表示形式の一覧 / グリッド、書式の太字 / 斜体)は toggle-btn-group、
表示する中身(パネル)の切替は tab、フォームの選択肢は radio、絞り込みのトグルは filter-chip、
操作が多くて並べきれないなら action-menu に畳む。主操作と副操作を並べるだけ(保存+キャンセル等)なら
グループにせず btn を間隔を空けて並べる。
使用法
推奨される使い方と、やりがちな NG パターン
OK
- ✓同じ対象に対する関連した操作を 2〜4 個つなげる(例: コピー / 切り取り / 貼り付け)。
- ✓グループの中は同じ variant(outline)・theme・サイズで揃え、1 つの部品に見せる。
- ✓role="group" と aria-label でグループに名前を付ける(何に対する操作か。例: 「テキストの編集」)。
- ✓アイコンだけのボタンは icon-btn にし、それぞれ aria-label で操作名を付ける。
- ✓分割ボタンは主操作の btn の右に icon-btn(chevron-down)をつなげ、action-menu でその他の操作を開く。
NG
- ✕solid / subtle / ghost のボタンをつなげない → 区切りが見えず 1 つのボタンに見える。グループは outline。
- ✕variant・theme・サイズの違うボタンを混ぜない → まとまりに見えない。
- ✕選択状態を持つ切り替え(表示形式・書式など)に使わない → toggle-btn-group(aria-pressed のトグルの並び)/ tab(中身の切替)/ radio(フォームの選択)。btn-group に aria-pressed を付けて代用しない。
- ✕関係の薄い操作(保存と削除など)をつなげない → 削除は離して置き、btn-negative にする。
- ✕5 個以上つなげない → action-menu に畳むか、よく使う操作だけを残す。
- ✕主操作(btn-primary solid)とキャンセルをグループにしない → 主従のある操作は btn を間隔を空けて並べる。
- ✕ページ遷移のリンクを並べない → 移動は link や tab / menu。
- ✕グループを入れ子にしない → 複数のまとまりはグループを間隔を空けて横に並べる。
outline で揃え、1 つの部品に見せる
見た目の一貫性すべて btn-neutral btn-outline の同じサイズ。境界線が 1 本につながり、まとまりとして読める。
<div class="btn-group" role="group" aria-label="テキストの編集"> <button class="btn btn-md btn-neutral btn-outline">コピー</button>… </div>
solid 同士は区切りが見えず 1 つのボタンに見える。variant・サイズの違うボタンを混ぜるとまとまりにも見えない。
<!-- solid をつなげない・サイズや variant を混ぜない --> <button class="btn btn-md btn-primary btn-solid">…<button class="btn btn-sm btn-neutral btn-outline">…
選択状態を持つ切り替えには使わない
用途の使い分け同じ内容の見え方を 1 つ選んで切り替えるなら トグルボタングループ。中身を切り替えるなら タブ、フォームの選択肢なら ラジオ。
<div class="toggle-btn-group" role="group" aria-label="表示形式" data-selection="single"> <button class="btn btn-md btn-neutral btn-ghost" aria-pressed="true">一覧</button>… </div>
ボタングループは「操作を実行する」ボタンの並び。aria-pressed を付けても選択中の見た目が付かず、どれが選ばれているか分からない。
<!-- 選択状態を持つ切り替えに btn-group + aria-pressed を使わない → toggle-btn-group --> <div class="btn-group"><button aria-pressed="true">一覧</button>…</div>
ボタングループのアクセシビリティ
見た目をつなげるだけの部品で、中はネイティブの <button> のままです。グループに role="group" と aria-label を付け、何に対する操作かを伝えます。WCAG 2.2 全基準は アクセシビリティ ページを参照。
期待される配慮
Presentation / Adaptability / Interaction / Assistive Technology
ボタンの区切りは境界線で示し、文字・アイコンのコントラストは各ボタンの基準(outline)を保つ。
幅が足りないときは折り返さず 1 行のまま。並べる数を 2〜4 個に抑え、320px 幅でも収まるようにする。
各ボタンが Tab で止まり、Enter / Space で実行。フォーカスリングは前面に出て隣に隠れない。
role="group" + aria-label で、ボタンの前にグループ名(「テキストの編集」)が読まれる。
DS が担保する機能
追加実装なしで満たされる
- ✓中はネイティブ
<button>のまま(役割・キーボード操作は btn / icon-btn と同じ) - ✓hover・フォーカス中のボタンを前面に出し、フォーカスリング(info/600)が隣のボタンに隠れない
- ✓強制カラーモードでも btn の輪郭線(ButtonText)でボタンの区切りが見える
- ✓sm(32px)以上のボタンでターゲット最小 24px を満たす
実装時の必須対応
プロダクト側で担保する
- !グループの要素に
role="group"とaria-label(何に対する操作か)を付ける - !アイコンだけのボタンには操作名の
aria-labelを付け、SVG はaria-hidden="true" - !処理中にグループごと disabled にしない(フォーカスが外れて位置を見失う)。押したボタンに
data-loadingを付ける - !矢印キーで移動するツールバーにしたい場合は
role="toolbar"と roving tabindex を JS で付与する(既定は各ボタンが Tab で止まる)
テスト方法
スクリーンリーダー / キーボード / 自動チェック
- SRグループに入ると「テキストの編集、グループ」が読まれ、続いて各ボタンの名前が読まれる
- キーTab で各ボタンに順に止まり、フォーカスリングが全周見える
- 自動axe / Lighthouse でボタンの名前(icon-btn の aria-label)とコントラストを確認
グループに名前を付ける
達成基準:WCAG 1.3.1 情報及び関係性グループ名「表示の拡大・縮小」と、各ボタンの「縮小」「拡大」が読まれる。
<div class="btn-group" role="group" aria-label="表示の拡大・縮小"> <button class="icon-btn …" aria-label="縮小">…</button> </div>
グループにもボタンにも名前が無いと「ボタン」「ボタン」としか読まれず、何の操作か分からない。
<div class="btn-group"> <!-- role / aria-label なし --> <button class="icon-btn …"><svg>…</svg></button> <!-- aria-label なし --> </div>