ナビゲーションメニュー

このページ

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

メニューを作成する

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

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

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

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

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