ナビゲーションメニュー

このページ

メニューを使用すると、エディターはサイトテンプレートを変更せずに順序付きリンクを管理できます。メニューには primary や footer などの安定した名前があり、翻訳されたメニューごとに個別のアイテムセットがあります。

メニューを作成する

EmDash 管理画面の Menus でメニューを作成して整理します。

  1. Create Menu をクリックして名前とラベルを入力します。テンプレートは名前を問い合わせ、ラベルは管理画面でメニューを識別します。

  2. Add Content をクリックしてエントリをリンクするか、Add Custom Link をクリックして外部 URL またはルート相対サイトパスを入力します。

  3. 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 を追加します。リクエストボディとレスポンスについてはメニューエンドポイントを参照してください。

ロケールルーティングとフォールバック設定については国際化を参照してください。