Disclosureについて - React Ariaの実装読むぞ
こんにちは、フロントエンドエンジニアの mehm8128 です。
今日は Disclosure について書いていきます。
最初にちょっと記事書いていたときはまだ本番環境のドキュメントに存在していなくて、http://localhost:1234/react-aria/useDisclosure.html
を貼ろうとしていたのですが、11 月のリリースで入ったようなので見れるようになっていました。
使用例
ドキュメントからそのまま取ってきています。
function Disclosure(props) {
let state = useDisclosureState(props);
let panelRef = React.useRef<HTMLDivElement | null>(null);
let triggerRef = React.useRef<HTMLButtonElement | null>(null);
let { buttonProps: triggerProps, panelProps } = useDisclosure(
props,
state,
panelRef
);
let { buttonProps } = useButton(triggerProps, triggerRef);
let { isFocusVisible, focusProps } = useFocusRing();
return (
<div className="disclosure">
<h3>
<button
className="trigger"
ref={triggerRef}
{...mergeProps(buttonProps, focusProps)}
style={{ outline: isFocusVisible ? "2px solid dodgerblue" : "none" }}
>
<svg viewBox="0 0 24 24">
<path d="m8.25 4.5 7.5 7.5-7.5 7.5" />
</svg>
{props.title}
</button>
</h3>
<div className="panel" ref={panelRef} {...panelProps}>
<p>{props.children}</p>
</div>
</div>
);
}
本題
APG はこちらです。
group
role とaria-
属性
ボタンとパネルを結びつけたり、現在 disclosure が開いているかどうかを表したりするために、いくつかのaria-
属性が用いられています。
aria-expanded
の boolean で現在開いているかどうかの状態を表し、aria-controls
でパネル(コンテンツ)と結びつけています。
また、非表示のときはaria-hidden
やhidden
属性がついています。
group
role が用いられているのは、detail
要素の暗黙の ARIA role がgroup
role だからです。
hidden="until-found"
hidden="until-found"
がつけられています。
詳しい説明は MDN に任せるのですが、disclosure が閉じている状態でもページ内検索などでは disclosure 内のコンテンツがヒットするようにし、その結果コンテンツまでスクロールされたらhidden
属性を外してコンテンツを表示するようにする、というものです。
ページ内検索やフラグメントナビゲーション(URL の後ろに#
をつけるやつ)で対象のコンテンツを表示しようとしたときにbeforematch
イベントが発火され、それを購読して以下のコードの箇所で処理を行っています。
なお、React 側がまだ対応していないので先ほどのコードのようにuseLayoutEffect
内で無理やり属性をつけていたり、Firefox と Safari がまだbeforematch
サポートしていないので対応しているブラウザのみで処理を行うようなロジックになっています。
まとめ
明日の担当は @mehm8128 さんで、番外編 テストについての記事です。お楽しみにー
Discussion