結果プレビュー付き検索モーダル
ボタンか ⌘K で検索モーダルを開き、左の結果リストを ↑↓ で辿ると右にプレビューが出る。空のときは「最近開いた」と「おすすめ」。Enter か「開く」で確定、Esc で閉じる。
プレビュー
クリック
操作クリック/タップで動きます。
仕様書
- 向く場面
- 社内ドキュメントなど開く前に中身を確かめたい検索
- ⌘K で開くコマンド型の検索
- 空のときに最近開いた・おすすめを出したい画面
- 避ける場面
- 結果がリンク1行で済む単純なサイト内検索
- スマホ幅が主(2ペインが縦積みになりプレビューが遠い)
- 構成要素
- 開くボタン(⌘K)
- オーバーレイ
- 検索入力欄
- 閉じる
- 結果リスト
- プレビュー(開くボタン)
- 持っている状態
- 通常
- ホバー
- フォーカス
- 押下中
- 空
- キーボード
⌘K/Ctrl+K で開閉。↑↓ で結果を循環、Enter で開く、Tab は入力欄・Esc・「開く」の間を循環、Esc で閉じる。閉じると開くボタンへフォーカスが戻る
- 支援技術
role=dialog・aria-modal・aria-label、開いている間は背後(ヘッダ・本文)を inert。入力は role=combobox+aria-activedescendant、結果は listbox/option+aria-selected。プレビューは aria-live=polite
- 動き
なし
デザインの要点
- 検索は「開く前に中身を確かめたい」場面が多い。プレビューがあれば、開いて違って戻る往復を1回に畳める
- 空の状態を空のままにしない。最近開いたものは高確率で目的地なので、入力前に並べる
- 閉じたら開いたボタンへフォーカスを戻す。キーボード利用者は「どこにいたか」を失うと戻れない
実装メモ
プレビューは枠内に収めるためオーバーレイを position:absolute(ステージ基準)にしています。実ページでは position:fixed にして body 直下に置いてください。開いている間はステージ内の他の要素(ヘッダ・本文)に inert を付け、Tab はモーダル内で循環させています。
コード(コピーして使えます)
<div class="smp-stage" id="smp-stage">
<header class="smp-app">
<span class="smp-logo">ミナト社内ドキュメント</span>
<button id="smp-open" class="smp-open" type="button">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
<span>検索</span><kbd>⌘K</kbd>
</button>
</header>
<div class="smp-body" aria-hidden="true">
<div class="smp-ghost" style="width:60%"></div>
<div class="smp-ghost" style="width:82%"></div>
<div class="smp-ghost" style="width:74%"></div>
<div class="smp-ghost" style="width:40%"></div>
</div>
<div id="smp-overlay" class="smp-overlay" hidden>
<div class="smp-modal" role="dialog" aria-modal="true" aria-label="検索">
<div class="smp-search">
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
<input id="smp-q" class="smp-input" type="text" placeholder="ドキュメント・人・議事録を検索" autocomplete="off" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="smp-list">
<button id="smp-close" class="smp-close" type="button" aria-label="閉じる">Esc</button>
</div>
<div class="smp-panes">
<ul id="smp-list" class="smp-list" role="listbox" aria-label="検索結果"></ul>
<section class="smp-preview" id="smp-preview" aria-live="polite"></section>
</div>
</div>
</div>
<p id="smp-status" class="smp-status" aria-live="polite"></p>
</div>