メニューを使用すると、エディターはサイトテンプレートを変更せずに順序付きリンクを管理できます。メニューには primary や footer などの安定した名前があり、翻訳されたメニューごとに個別のアイテムセットがあります。
メニューを作成する
EmDash 管理画面の Menus でメニューを作成して整理します。
-
Create Menu をクリックして名前とラベルを入力します。テンプレートは名前を問い合わせ、ラベルは管理画面でメニューを識別します。
-
Add Content をクリックしてエントリをリンクするか、Add Custom Link をクリックして外部 URL またはルート相対サイトパスを入力します。
-
Move up と Move down を使用して順序を設定します。アイテムを編集して Parent を選択するとネストできます。
すべてのロケールで同じメニュー名を使用します。多言語サイトでは、メニューを開いて Translations パネルを使用して他のロケールバージョンを作成・編集します。EmDash は同じコンテンツやタクソノミー用語の翻訳を接続した状態に保つため、getMenu() はリクエストされたロケールのラベルとスラッグを使用できます。
メニューリンクの解決方法
コンテンツおよびタクソノミーメニューアイテムは、完成した URL ではなく参照を保存します。テンプレートが getMenu() を呼び出すと、EmDash は現在のコレクションとロケールデータを使用してその参照を解決します。
| メニューアイテムの種類 | テンプレートに返される URL |
|---|---|
| コンテンツエントリ | コレクションの urlPattern、またはコレクションにパターンがない場合は /{collection}/{slug} |
| タクソノミー用語 | 解決された用語翻訳を使用した /{taxonomy}/{slug} |
| コレクションアーカイブ | /{collection}/ |
| カスタムリンク | エディターが入力した外部 URL またはルート相対パス |
返される各アイテムにはラベル、オプションのターゲット、title 属性、CSS クラス、ネストされた children も含まれます。以下のレンダリング例ではこれらの値を直接使用します。
メニューをレンダリングする
サーバーレンダリングされた Astro コンポーネントで getMenu() を呼び出します。名前が存在しない場合は null を返します。
以下のレイアウトはプライマリメニューと1レベルのネストされたアイテムをレンダリングします:
---
import { getMenu } from "emdash";
import { getRelativeLocaleUrl } from "astro:i18n";
const locale = Astro.currentLocale;
const menu = await getMenu("primary", { locale });
function menuHref(url: string) {
return locale && url.startsWith("/")
? getRelativeLocaleUrl(locale, url)
: url;
}
---
{menu && menu.items.length > 0 && (
<nav aria-label="メインナビゲーション">
<ul>
{menu.items.map((item) => {
const href = menuHref(item.url);
return (
<li class:list={item.cssClasses}>
<a
href={href}
target={item.target}
rel={item.target === "_blank" ? "noopener noreferrer" : undefined}
title={item.titleAttr}
aria-current={Astro.url.pathname === href ? "page" : undefined}
>
{item.label}
</a>
{item.children.length > 0 && (
<ul>
{item.children.map((child) => {
const childHref = menuHref(child.url);
return (
<li class:list={child.cssClasses}>
<a
href={childHref}
target={child.target}
rel={child.target === "_blank" ? "noopener noreferrer" : undefined}
title={child.titleAttr}
aria-current={Astro.url.pathname === childHref ? "page" : undefined}
>
{child.label}
</a>
</li>
);
})}
</ul>
)}
</li>
);
})}
</ul>
</nav>
)}
getMenu() はまず明示的な locale を選択し、次に現在のリクエストロケール、その後設定されたデフォルトロケールを選択します。そのロケールにメニューまたは参照されたエントリがない場合、検索は設定されたフォールバックチェーンに従います。
メニューアイテム URL にはコレクション URL パターンまたはタクソノミーパスが含まれますが、Astro のロケールプレフィックスは含まれません。menuHref() ヘルパーはルート相対リンクにそのプレフィックスを追加し、外部リンクはそのままにします。
この例は1つの子レベルをレンダリングし、典型的なドロップダウンをカバーします。エディターがより深いナビゲーションを作成できる場合、アイテムのマークアップを各アイテムの children を同じルールでレンダリングする再帰コンポーネントに移動します。
ウィジェットエリアでメニューを使用する
メニューウィジェットは既存のメニューをウィジェットエリア内に配置します。ウィジェットは現在のリクエストロケールのメニューを読み取ります。サイトにカスタムネストマークアップや明示的なロケール URL 処理が必要な場合は、上記の直接レンダリングパターンを使用します。
メニューデータを直接クエリする
テンプレートが1つのメニューのアイテムではなく利用可能なメニュー定義を必要とする場合は getMenus() を使用します。ランタイム API リファレンスでクエリシグネチャと戻り値を確認できます。
プログラムによるメニュー変更の場合、Bearer トークンで認証し、状態を変更するすべてのリクエストに X-EmDash-Request: 1 を追加します。リクエストボディとレスポンスについてはメニューエンドポイントを参照してください。
ロケールルーティングとフォールバック設定については国際化を参照してください。