commit d980f4cf2f0930fceac109424c419950ef72749c Author: Jakub Zych Date: Mon Oct 12 18:19:53 2026 +0200 feat: MenuNav layer for the SummerCMS menu API - typed client and useMenu/useMenuApi (SSR, menu:: key, server and public bases, x-forwarded-for forwarded also on cached renders) - MenuNav and recursive MenuNavItem: WAI disclosure navigation, URL allowlist with a text fallback, rel on _blank, active link and trail, mobile toggle, Esc / focus-out / outside pointer / route change closing - menu tokens and base CSS, README - node tests (link rules, client, server-rendered NavItem) and a playground SSR smoke against a fixture API diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b042b30 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +node_modules/ +.nuxt/ +.output/ +.data/ +.playground/.nuxt/ +.playground/.output/ +.env +app/components/Menu/.navitem-*.compiled.ts diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..85e5027 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22.22.0 diff --git a/.playground/app/app.vue b/.playground/app/app.vue new file mode 100644 index 0000000..3db37b1 --- /dev/null +++ b/.playground/app/app.vue @@ -0,0 +1,24 @@ + + + diff --git a/.playground/nuxt.config.ts b/.playground/nuxt.config.ts new file mode 100644 index 0000000..cb4d490 --- /dev/null +++ b/.playground/nuxt.config.ts @@ -0,0 +1,6 @@ +// Local playground: an app that only extends the layer and renders one menu +// (app.vue). testing/smoke-ssr.mjs builds it against the fixture API. +export default defineNuxtConfig({ + extends: ['..'], + compatibilityDate: '2025-07-15', +}) diff --git a/README.md b/README.md new file mode 100644 index 0000000..e58c06b --- /dev/null +++ b/README.md @@ -0,0 +1,128 @@ +# vue-menu-layer + +A Nuxt 4 layer that renders a menu of the SummerCMS menu plugin as an accessible site navigation. + +```bash +pnpm add git+https://git.golem15.com/golem15/vue-menu-layer.git#v0.1.0 +``` + +## Overview + +The layer is consumed with `extends: ['vue-menu-layer']`. It reads one route of the menu plugin's anonymous API, `GET /_menu/api/v1/menus/{code}`, during SSR, so the first paint already has the menu, and renders it with ``. Editors manage menus in the SummerCMS admin; the site needs no menu data of its own. + +The layer is neutral: it ships no site colours, no site copy and no Nuxt modules. Its look comes from `--menu-*` CSS custom properties, which an app overrides, and every component can be replaced by a file of the same name in the app. + +## Features + +- **`MenuNav`**: a `