たまたまぶち当たったので備忘録。
前提と経緯
- 最新の HTML Standard において、details 要素に name 属性が使用できる
- Astro (v.4.2.1) で details 要素に name 属性を使ったら、
astro check
で怒られた HTMLAttributes
型を拡張して対応した
details 要素の仕様
details 要素の仕様は下記ですが、name 属性が使用できることが確認できます。確か昨年の 10 月くらいにこの修正がマージされたのをみた記憶があるので最近ですが。
で、この記事執筆時点で Firefox 以外の主要ブラウザではサポートされています。
details 要素に name 属性によって同一の名前を付与することで、複数の details 要素をグループ化し、グループ内の details 要素が 1 つ開いたら、他を閉じる、といった、所謂排他的動作をさせることが可能です。
例えば下記のように記述することで、「HTML」 を開いた状態で、「CSS」 の方を開くと、「HTML」 が自動的に閉じてくれます。
<details name="content-menu">
<summary>HTML</summary>
<ul>
<li><a href="#">HTML5 タグリファレンス</a></li>
<li><a href="#">HTML5 の基礎知識</a></li>
<li><a href="#">HTML5 に関するリンク集</a></li>
</ul>
</details>
<details name="content-menu">
<summary>CSS</summary>
<ul>
<li><a href="#">CSS リファレンス</a></li>
<li><a href="#">CSS の基礎知識</a></li>
<li><a href="#">CSS に関するリンク集</a></li>
</ul>
</details>
astro check
で怒られる件
で、普通に details 要素に name 属性を書いたら、astro check
時に、
error ts(2322): Type '{ children: any[]; name: string; }' is not assignable to type 'DetailsHTMLAttributes'.
Property 'name' does not exist on type 'DetailsHTMLAttributes'.
<details name="example">
がでて怒られましたとさ。
HTMLAttributes
型を拡張する
Astro はマークアップが有効な HTML の属性を使用しているか確認するために、HTMLAttributes
型を提供してくれていますが、この中で details 要素に対する name 属性が定義されていないので型チェックでエラーになります。ということで name 属性を追加することで回避しました。
プロジェクトのルートディレクトリに custom-attributes.d.ts
を新規作成し、下記の内容で保存します。これだけ。
// details 要素に name 属性を付与できるように型定義
declare namespace astroHTML.JSX {
interface IntrinsicElements {
details: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
name?: string;
};
}
}
恐らく、今後の Astro のアップデートで勝手に解決するとは思いますが、とりあえずの回避措置として。
ちなみに下記のようにして、全要素に独自の属性を追加することもできますが、あまり適用範囲が広すぎるのもあれなので、前述の通り、details 要素のみ対象にするようにしています。
declare namespace astroHTML.JSX {
interface HTMLAttributes {
'foo'?: number;
'bar'?: string;
}
}