006_animation
高さアニメーション付きのアコーディオンです。grid-template-rows: 0fr → 1fr を使い、
パネルの開閉時に 200ms ease-out でなめらかに高さがトランジションします。
骨格は snippet 001 / 004 / 005 と同じ aria-expanded + hidden パターンを継承し、
開く時は「hidden除去 → aria-expanded="true" → 高さアニメ開始」、
閉じる時は「aria-expanded="false" → 高さアニメ → 完了後にhidden付与」という順序で
支援技術と視覚表現を一致させています。
height: auto はトランジション対象になりませんが、
grid-template-rows の 0fr → 1fr はモダンブラウザでアニメーション可能です。
外側 __body をグリッドコンテナにし、内側 __content に min-height: 0 と
overflow: hidden を当てることで、コンテンツの実寸を計測せずに「閉じきった状態」と「中身ぴったりの高さ」を行き来できます。
max-height ハック(仮の最大値を指定する手法)と違って、コンテンツが何行になっても
正確に「ちょうどの高さ」へアニメーションする点が利点です。
開く時は即時にhiddenを外し、その直後に aria-expanded="true" を立ててから
高さアニメーションを開始します。hidden が付いたままだと CSS の高さアニメーション対象が描画されないためです。
閉じる時は逆にhiddenを遅延付与します。aria-expanded="false" を即座に切り替えてから高さアニメーションを再生し、
完了(transitionend)の通知を受けてから hidden を付けます。
アニメ中に hidden を付けると支援技術が「途中で消えた」状態になり、視覚と読み上げが乖離してしまうためです。
OS の「視差効果を減らす」設定が有効な場合、transition: none を当てて
高さアニメーションを無効化します。前庭機能障害等で動きの強い演出が苦手なユーザーへの配慮です。
この時 JS 側は transitionend が発火しないため、閉じる時の hidden 付与を
即時パスへ切り替えています(transition の duration が 0 のときは
視覚的な遷移がないので「アニメ中の不一致」も発生しません)。
HTML 構造・FLOCSS 命名(c-accordion / __header / __icon / __body / __content)・
JS シグネチャ(setItemState(header, open) / collectHeaders(root) / bindAccordion(root))は
すべて 001 / 004 / 005 と同一です。
違いは CSS の __body に display: grid + grid-template-rows: 0fr/1fr のアニメーションを当てた点と、
JS の setItemState 内で hidden 付与のタイミングを transitionend に遅延させた点の2つだけです。
個別開閉の挙動は 001 と同等(複数同時に開ける)になります。