next.jsで作ってみたブログにamp-sidebarを導入する
TL;DR
モバイルページでもサイドバーはやはりほしい。そして最近のはやりはfloating buttonみたいなやつを押すとサイドバーが開く、というものである...気がする。もちろん、onClickやらを使えばかんたんに実装できるのだが、ampに対応しているとonClickは許されていない。
そういうときに使えるのがamp-sidebarである。しかし、Reactやnext.jsでamp-sidebarを導入している事例は少なく、material-uiやtypescriptと一緒にやっている例は見つからなかった。一応実装できたので、参考になる人がいることを祈って記事に残しておく。
amp-sidebar
普段は隠れていて、ボタンを押すと表示され、サイドバー以外の部分を押すと閉じる、という機能がデフォルトで実装されている。 とりあえず公式の例を見てみる。
基本的には、amp-sidebarでidを指定し、buttonのonにtap:{id}.toggleをつければ、そのボタンで開閉ができるようになる。このtoggleの部分は他にも可能で
| action | desc |
|---|---|
| open (default) | サイドバーを開く |
| close | サイドバーを閉じる |
| toggle | サイドバーを開閉する |
の3つが使える。基本的にtoggleでいい気がする。
なので、
のようなjsxを書けばいいことがわかる。
しかし、buttonにon属性はないので、Typescriptを使う場合はonを型定義する必要があることに注意が必要(ts-ignoreでもいいかもしれないが...)。
Float Button
こちらは簡単で@material-ui/core/Fabを使えばOK。ただ、このままだと場所が固定されておらず、onが定義されていないのでそのへんを定義する必要がある。
まず型定義は基本的に同じところからexportされているxxxPropsというものを使う。今回の場合はFabPropsをFabと一緒にimportする。このbuttonはonを必ず使う用途だと考えているのでdefaultpropsの拡張は行っていない。
AmpFab.tsx
場所の定義はここでやってしまってもいいが、amp-sidebarとAmpFabをあわせてAmpSidebarコンポーネントを作成したかったので、そこで定義することにした。
AmpSidebar(amp-sidebar+float button)
画面が大きいときは固定したサイドバーを表示するので、固定したサイドバーが表示されなくなったときにFabが表示されるように設定してある。右下に固定するのに必要な部分は以下のcss部分。
注意が必要なのは、amp-sidebarは<body>の直下にないとだめなので、<div>などで囲ってしまうと、Warningが表示される。なので、Fragmentで囲う必要がある。
AmpSidebar.tsx
Layoutにimportする
デフォルトの_document.jsは以下である。このサイトでは、_document.jsにampsidebarを直接入れる必要がある、とされている。しかし、このpagesの中身が入る部分である<Main>はfragmentで囲われたものなので、この中にamp-sidebarを入れてもWarningは表示されない。ただし、material-uiのContainerやもっと単純にdivなどで囲ってしまうとWarningが表示されるので、できるだけ上の方のコンポーネントにamp-sidebarを入れる必要がある。
_document.js
例えば、以下のようにする。これを標準レイアウトにすればWarningは表示されない。
Layout.tsx