ADR-0066: コードを動かす画面の詰めたペイン、木の行の中の名前の欄、SplitPane の仕切りで、フォーカスの輪を要素の内側に引く¶
Status¶
承認
Context¶
コードを動かす画面のペインを隙間なく並べ、行を 24px に詰めたときの、フォーカスの表示を決める必要がある。
- フォーカスの表示は、要素から 2px 離して引く墨の 2px の輪で、
focus-ringの 1 つのユーティリティで書くと決めている。例外は検索の欄だけである。 - コードを動かす画面だけ、文字を 12px と 13px まで、押せる領域を 24×24 CSS px まで小さくすると決めている。
- コードを動かす画面は、ペインの間の隙間と外側の余白をなくし、木の行を 24px、HTTP の流れの行を約 44px に詰めた。
- 外へ広がる輪は、次の所で欠けるか、隣に掛かる。
- スクロールする領域の中で、領域の幅いっぱいの木の行と HTTP の流れの行の輪は、左右が領域の端で切れる。
- 24px の木の行が隙間なく並ぶので、輪が上下の行に 4px 掛かる。
- ペインの全体を占める、スクロールする領域(コンソールの行の領域、エディタのエンジン)の輪は、隣のペインと題の帯に出るか、ペインの端で切れる。
- エディタのタブの並びは横にスクロールするので、タブの輪の上下が切れる。
- VS Code と Chrome の DevTools は、一覧の行のフォーカスを、行の内側に引く枠で示す。
- ファイルの木(
FileTree)は、作成と名前の変更を、木の行の中の名前の欄で行う。- 木の行は 24px で、上下に 2px の余白がある。名前の欄は 20px の高さで、1px の枠(
border-field)を持つ。 - 欄のある行に内側の輪を引くと、輪の内側の線が欄の枠の上辺と下辺に接する。
- 上下は、墨の 2px の輪と 1px の枠がつながり、3px の帯に見える。右は、6px をあけて縦の線が 2 本並ぶ。
- 名前に誤りがあるときは、赤の枠が墨の輪の中に見え、二重の枠になる。
- 欄のある行の輪は 1 重の輪にならず、ほかの行の輪とも見え方が違う。
- VS Code のエクスプローラーは、行の中の名前の欄のフォーカスを、欄の 1 本の枠で示し、行には輪を出さない。名前に誤りがあるときは、その枠を赤に替える。 どちらも記憶によるもので、実物で比べていない(未確認)。
- 木の行は 24px で、上下に 2px の余白がある。名前の欄は 20px の高さで、1px の枠(
- フォーカスの表示は、1 つのユーティリティ(墨の 2px の 1 重の輪)だけを使い、コンポーネントごとに色や太さを変えない(
FOCUS-ONE)。 - 分割の幅を変える
SplitPaneの仕切りは、マウスで押す端末の PC の配置では、ペインの間の 8px の余白に置く。8px の幅の外に 2px 離して輪を引くと、両側のペインの面に重なる。
Decision¶
- テーマ変数のファイルに、
focus-ring-insetのユーティリティを足す。色と太さはfocus-ringと同じ墨の 2px で、輪を要素の内側に 2px 入れて引く(outline-offset: -2px)。 - 使う所は、コードを動かす画面のコンポーネントの次の要素に限る。
TreeViewのdensity="compact"の項目。名前の欄を描いている行には、フォーカスの輪を引かない。欄が、自分のフォーカスの表示を持つ。FileTreeの名前の欄。輪は欄の 1px の枠に重ねて、欄の内側に引く。- 名前に誤りがあるときも、輪は墨のままにする。誤りは、欄の下の印と理由の文と、
aria-invalidで示す。
- 名前に誤りがあるときも、輪は墨のままにする。誤りは、欄の下の印と理由の文と、
Tabsのdensity="compact"のタブと、マウスで押す閉じるボタンHttpExchangeListの行- 分割の幅を変える
SplitPaneの仕切り - ペインの全体を占める、フォーカスできるスクロールする領域。当たるのは、
ConsoleEntryListの行の領域と、カタログの見本のエンジン(DummyEngine)である。- この領域には
focus-ring-insetを付けない。領域自身に輪を引かない。中の行や帯の背景が、領域自身の輪を上から塗って欠けさせるためである。領域を 1 つだけ直下に置く外側の要素にfocus-ring-frameを付け、直下の領域にフォーカスが来たときに、外側の要素の::afterへ同じ輪を内側に重ねて引く。
- この領域には
- プレイグラウンドの実物のエディタと端末のエンジンは、コードを動かす画面の ToolPane に入れるときに、同じ内側の輪にする。付ける作りは、エンジンごとに、その画面を作る issue(#95、#99、#100)で決める。
- ほかの要素は、
focus-ringのままにする。 - 理由は次のとおり。
- 輪が要素の中に収まるので、隣の行に掛からず、領域の端で切れない。行の密度も変えずに済む。
- VS Code と DevTools の一覧の行と同じ表示で、利用者が見慣れている。
- 名前の欄は、欄の枠と輪が重なるので、表示が 1 重の輪になる。
- 名前の欄の輪の位置が、名前を打つ範囲と同じになる。
- 名前に誤りが無いときは、記憶にある VS Code の行の中の欄と同じ表示になる(実物で比べていない。未確認)。
FOCUS-ONEの例外に、focus-ring-insetとfocus-ring-frameの 2 つを足す。
Verification¶
カタログの「画面/コードを動かす画面」を、Chromium の 1600x900 で開いて確認した。
- 木の行と HTTP の流れの行にキーボードでフォーカスを置くと、輪は行の中に収まり、上下の行とペインの端に掛からなかった。ライトとダークの両方で見た。
- compact のタブは、コンポーネントのテストで、フォーカスしたときの輪が要素の内側(
outline-offset: -2px)に引かれることを確認した。 - コンソールの行の領域とカタログの見本のエディタのエンジンは、コンポーネントのテストで、外側の要素の
::afterに内側の輪が引かれ、領域自身の輪が出ないことを確認した。エンジンの輪が、カーソルのある行の帯と行番号の列で欠けないことは、画面でも撮って確認した。端末の見本のエンジンも、テストで同じことを確認した。 - 内側の輪が WCAG 2.2 の達成基準 2.4.13(AAA)を満たすかを、次のとおり確認した。
- 太さ:
focus-ring-insetとfocus-ring-frameの輪は、どちらもoutline: 2px solidで、2px 以上である(theme.cssの値)。 - 面積: 輪は要素の外周の内側 2px に引くので、面積は外周の 2px の帯と等しい。
- コントラスト:
pnpm run check:contrastが、輪の色と面の組を 3:1 以上で確認する。組には、選んだ行(primary-surface)、コードの面、warning-surface、danger-surfaceを含み、ライトとダークの 108 組が届いた。 - 隠れ: 外側の要素の
::afterが最前面に出るので、カーソルのある行の帯と行番号の列に隠れない。画面で確認した。 - 画素単位の、フォーカスの前後の同じ画素のコントラストは、測っていない(未確認)。面の色との組で代える。
- 太さ:
- 実物のエディタと端末のエンジンの現状は、次のとおり。どちらも、この ADR の対象のコンポーネントには入っていない。
- SQL のエディタ(
apps/playground/src/sql-console/SqlConsole.tsx)は、囲む要素にhas-[.cm-focused]:focus-ringを付け、輪を外へ引く。.cm-focusedは、フォーカスを受ける.cm-contentの外側の要素に付く。- そのため、
focus-ring-frameの「直下の:focus-visible」の条件に当たらない。
- そのため、
- Go の端末(
apps/playground/src/go/GoPage.tsx)は、スクロールするpreにfocus-visible:focus-ringを付け、輪を外へ引く。このpreは、focus-ring-frameの直下に置けば、同じ内側の輪になる。 - 実物のエンジンを ToolPane に入れたときの輪の見た目は、撮っていない(未確認)。
- SQL のエディタ(
- 選んだ木の行(
primary-surface)の上でも、墨の輪は見えた。輪と面の組は、ADR-0061 でコントラストのチェックに入れてある。 - Safari と Firefox での確認はしていない。
名前の欄は、次のとおり確認した。
- 単体テストで、名前の欄の輪が
outline: 2px solidでoutline-offset: -2pxであり、欄の行に輪が無いことを確認した。 - カタログの
コンポーネント/Case/FileTreeを Chromium で開き、作成、名前の変更、名前の誤りの 3 つを、ライトとダークで静止画に撮って見た。輪は欄の枠に重なって 1 重に見え、欄の文字は輪に欠けなかった。 - ハイコントラストでの見え方は、画面で見ていない(未確認)。輪は
outlineなので残るが、枠と輪が同じ色になり、フォーカスの前後の違いは線の太さだけになる見込みである。
Considered Options¶
詰めたペインの行と枠の輪の案は、次の 3 つ。
| 選択肢 | 強み | 弱み |
|---|---|---|
| 採用: 詰めたペインの行と枠だけ、内側に輪を引く | 輪が欠けず、隣にも掛からない。行の密度を変えない。VS Code と DevTools と同じ表示 | フォーカスの表示が 2 つになる。内側の輪は、行の中の文字や印に近づく |
| スクロールする領域と行の間に 4px の余白を足し、外へ広がる輪のままにする | フォーカスの表示が 1 つのまま | 木の行の間が広がり、DevTools と VS Code に近い密度にならない |
| 今のまま、欠けた輪を受け入れる | 変更が無い | 左右が欠けた輪は上下の 2 本の線になり、輪の形で見つけにくい。上下の行の文字に掛かる |
木の行の中の名前の欄の輪の案は、次の 3 つ。
| 選択肢 | 強み | 弱み |
|---|---|---|
| 採用: 欄に内側の輪を引き、行には引かない | 1 重の輪になる。輪の位置が打つ範囲と同じ。記憶にある VS Code の表示と同じ(未確認) | 欄は開いている間ほぼ常にフォーカスを持つので、誤りの赤の 1px の枠は、ほかのウィンドウへ移ったときのほかは見えない。focus-ring-inset を使う所が 1 つ増える |
| 行の輪を残し、欄を低くして輪との間を空ける | 行に輪を引く形を変えない | 欄が 16px になり、13px の文字が欠けるおそれがある |
| 今のまま、行の輪と欄の枠を並べる | 変更が無い | 二重の枠に見え、1 重の輪にならない |
Consequences¶
Positive¶
- 詰めたペインで、どの行と枠にフォーカスがあるかを、欠けない輪で示せる。
- 名前の欄のフォーカスを、ほかの要素と同じ 1 重の輪で示せる。
Negative¶
- フォーカスの表示のユーティリティが 3 つになる。
focus-ring-insetとfocus-ring-frameをコードを動かす画面の外で使っていないかは、レビューで見る。 - 内側の輪は、行の背景の面の上に出る。行の面とのコントラストは、ADR-0061 がコントラストのチェックに入れた、輪と面の組で確認する。
- 名前の欄は、フォーカスが外れると確定か取り消しで閉じるので、開いている間ほぼ常にフォーカスを持つ。そのため、ほかのウィンドウへ移ったときのほかは、名前の誤りを赤の枠で示せない。誤りは、欄の下の印と理由の文と、
aria-invalidで示す。 TreeViewのeditorに欄を渡す側が、欄のフォーカスの表示を受け持つ。