@riebeckite/plugin-navigation 0.0.27 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,8 +5,8 @@
5
5
  Site navigation as a Riebeckite plugin. `navigation()` derives the primary
6
6
  navigation from the notes already in the vault, so an existing Obsidian vault
7
7
  becomes navigable with no Riebeckite-specific file and no required frontmatter.
8
- The plugin owns the navigation *model* and the *rendering mechanics*; the Site
9
- owns placement — where each rendered list appears.
8
+ The plugin owns the navigation *model*, rendered UI, and interaction styling;
9
+ the Site owns placement — where each rendered navigation appears.
10
10
 
11
11
  [日本語](./README_ja.md)
12
12
 
@@ -56,23 +56,32 @@ site without navigation keeps working.
56
56
 
57
57
  ### Rendering
58
58
 
59
- `SiteNav` renders a resolved tree as a `<nav>` landmark with nested lists. It
60
- owns the rendering mechanics — recursive children, active-path detection,
61
- locale-aware normalization, external-link handling, and `aria-current` — and
62
- ships the structural CSS for that `rb-nav` tree in its own `style.css`, loaded
63
- through the generated plugin styles. The Site decides where the tree is placed
64
- and whether to wrap it in a `<details>` element on small screens:
59
+ `SiteNav` renders a resolved tree as a `<nav>` landmark with nested lists.
60
+ `MobileSiteNav` renders its compact `<details>` menu. The plugin owns both
61
+ components' `rb-nav` UI — list flow, links, nested menus, focus treatment, and
62
+ the mobile panel — in its own `style.css`, loaded through the generated plugin
63
+ styles. The Site places the component roots in its own layout wrappers; it must
64
+ not style `rb-nav` descendants or construct the mobile menu markup:
65
65
 
66
66
  ```tsx
67
- import { SiteNav } from "@riebeckite/plugin-navigation";
67
+ import { MobileSiteNav, SiteNav } from "@riebeckite/plugin-navigation";
68
68
 
69
69
  <header class="site-header rb-site-header">
70
70
  <a href="/" class="site-header__home rb-site-header__home">My Site</a>
71
- <SiteNav
72
- items={primary}
73
- path={c.req.path}
74
- language={c.get("htmlLanguage")}
75
- />
71
+ <div class="site-header__primary-navigation">
72
+ <SiteNav
73
+ items={primary}
74
+ path={c.req.path}
75
+ language={c.get("htmlLanguage")}
76
+ />
77
+ </div>
78
+ <div class="site-header__mobile-navigation">
79
+ <MobileSiteNav
80
+ items={primary}
81
+ path={c.req.path}
82
+ language={c.get("htmlLanguage")}
83
+ />
84
+ </div>
76
85
  </header>;
77
86
  ```
78
87
 
@@ -82,6 +91,14 @@ active item, so unlocalized authored hrefs still match localized pages. Pass
82
91
  `localizeHref` to rewrite hrefs for the current language, `label` to change the
83
92
  landmark label, and `class`/`className` to extend the `<nav>` classes.
84
93
 
94
+ For an intentional root-level visual override, set these public custom
95
+ properties on the `SiteNav` root or a wrapper: `--rb-nav-gap`,
96
+ `--rb-nav-list-flex-wrap`, `--rb-nav-list-justify-content`,
97
+ `--rb-nav-item-display`, `--rb-nav-item-padding`,
98
+ `--rb-nav-item-font-family`, `--rb-nav-item-font-size`,
99
+ `--rb-nav-item-font-weight`, `--rb-nav-item-letter-spacing`, and
100
+ `--rb-nav-item-text-transform`. Do not select `rb-nav` descendants.
101
+
85
102
  ## Authored navigation
86
103
 
87
104
  Automated derivation cannot express everything, and some sites curate their
@@ -140,8 +157,9 @@ tab.
140
157
  the model, or `null`
141
158
  - `validateNavigationOptions(options)` — option validation
142
159
  - `SiteNav` — render a resolved tree with the standard `rb-nav` structure
160
+ - `MobileSiteNav` — render the plugin-owned compact navigation menu
143
161
  - Types: `NavigationItem`, `NavigationOptions`, `NavigationSource`,
144
- `SiteNavigation`, `SiteNavProps`
162
+ `SiteNavigation`, `SiteNavProps`, `MobileSiteNavProps`
145
163
 
146
164
  ## Limitations
147
165
 
package/README_ja.md CHANGED
@@ -5,7 +5,7 @@
5
5
  サイトナビゲーションを提供する Riebeckite プラグインです。`navigation()` は
6
6
  Vault にすでにあるノートから主要ナビゲーションを導出します。Riebeckite 専用の
7
7
  ファイルも必須 frontmatter も不要なので、既存の Obsidian Vault をそのまま
8
- 公開できます。ナビゲーションの「モデル」と描画の仕組みはプラグインが持ち、
8
+ 公開できます。ナビゲーションの「モデル」、UI、操作に関わるスタイルはプラグインが持ち、
9
9
  配置は Site が担当します。
10
10
 
11
11
  [English](./README.md)
@@ -57,22 +57,32 @@ const secondary = model?.secondary ?? [];
57
57
  ### 描画
58
58
 
59
59
  `SiteNav` は解決済みのツリーを `<nav>` ランドマークとネストしたリストとして
60
- 描画します。子の再帰描画、現在パスの判定、言語を考慮した正規化、外部リンクの
61
- 扱い、`aria-current` といった描画の仕組みを担当し、その `rb-nav` ツリーを
62
- 成立させる構造 CSS を自身の `style.css` に同梱します(自動生成される plugin
63
- styles 経由で読み込まれます)。ツリーをどこに置くか、モバイルで `<details>` を
64
- 使うかは Site が決めます。
60
+ 描画し、`MobileSiteNav` はコンパクトな `<details>` メニューを描画します。子の
61
+ 再帰描画、現在パスの判定、言語を考慮した正規化、外部リンクの扱い、`aria-current`
62
+ に加え、リスト・リンク・子メニュー・フォーカス表示・モバイルパネルの `rb-nav` UI は
63
+ プラグインが自身の `style.css` で担当します(自動生成される plugin styles 経由で
64
+ 読み込まれます)。Site はコンポーネントの root を独自のレイアウト用ラッパーに置き、
65
+ `rb-nav` の子要素をスタイルしたりモバイルメニューのマークアップを組み立てたりしません。
65
66
 
66
67
  ```tsx
67
- import { SiteNav } from "@riebeckite/plugin-navigation";
68
+ import { MobileSiteNav, SiteNav } from "@riebeckite/plugin-navigation";
68
69
 
69
70
  <header class="site-header rb-site-header">
70
71
  <a href="/" class="site-header__home rb-site-header__home">My Site</a>
71
- <SiteNav
72
- items={primary}
73
- path={c.req.path}
74
- language={c.get("htmlLanguage")}
75
- />
72
+ <div class="site-header__primary-navigation">
73
+ <SiteNav
74
+ items={primary}
75
+ path={c.req.path}
76
+ language={c.get("htmlLanguage")}
77
+ />
78
+ </div>
79
+ <div class="site-header__mobile-navigation">
80
+ <MobileSiteNav
81
+ items={primary}
82
+ path={c.req.path}
83
+ language={c.get("htmlLanguage")}
84
+ />
85
+ </div>
76
86
  </header>;
77
87
  ```
78
88
 
@@ -83,6 +93,14 @@ import { SiteNav } from "@riebeckite/plugin-navigation";
83
93
  `label` でランドマークのラベルを、`class` / `className` で `<nav>` のクラスを
84
94
  拡張できます。
85
95
 
96
+ root レベルで意図的に見た目を上書きする場合は、`SiteNav` の root またはラッパーに
97
+ 次の公開カスタムプロパティを指定します。`--rb-nav-gap`、
98
+ `--rb-nav-list-flex-wrap`、`--rb-nav-list-justify-content`、
99
+ `--rb-nav-item-display`、`--rb-nav-item-padding`、
100
+ `--rb-nav-item-font-family`、`--rb-nav-item-font-size`、
101
+ `--rb-nav-item-font-weight`、`--rb-nav-item-letter-spacing`、
102
+ `--rb-nav-item-text-transform` です。`rb-nav` の子要素は選択しません。
103
+
86
104
  ## 手書きナビゲーション
87
105
 
88
106
  自動導出ですべてを表現できるわけではなく、リンクを意図的に整えたいサイトも
@@ -133,16 +151,17 @@ navigation({
133
151
 
134
152
  ## エクスポート
135
153
 
136
- - `navigation(options?)` — プラグインファクトリ
137
- - `navigationPlugin` — `navigation` のエイリアス
138
- - `NAVIGATION_PLUGIN_NAME` — プラグイン名 `"navigation"`
139
- - `buildNavigation(entries, options?)` — マニフェストエントリからモデルを構築する
140
- - `resolveSiteNavigation(config, manifest)` — 有効なプラグインを見つけてモデルを
154
+ - `navigation(options?)`:プラグインファクトリ
155
+ - `navigationPlugin`:`navigation` のエイリアス
156
+ - `NAVIGATION_PLUGIN_NAME`:プラグイン名 `"navigation"`
157
+ - `buildNavigation(entries, options?)`:マニフェストエントリからモデルを構築する
158
+ - `resolveSiteNavigation(config, manifest)`:有効なプラグインを見つけてモデルを
141
159
  構築する。なければ `null`
142
- - `validateNavigationOptions(options)` — オプションの検証
143
- - `SiteNav` — 解決済みツリーを標準の `rb-nav` 構造で描画する
160
+ - `validateNavigationOptions(options)`:オプションの検証
161
+ - `SiteNav`:解決済みツリーを標準の `rb-nav` 構造で描画する
162
+ - `MobileSiteNav`:プラグイン所有のコンパクトなナビゲーションメニューを描画する
144
163
  - 型: `NavigationItem`, `NavigationOptions`, `NavigationSource`,
145
- `SiteNavigation`, `SiteNavProps`
164
+ `SiteNavigation`, `SiteNavProps`, `MobileSiteNavProps`
146
165
 
147
166
  ## 制約
148
167
 
@@ -19,6 +19,9 @@ export type SiteNavProps = {
19
19
  readonly className?: string;
20
20
  readonly omitHome?: boolean;
21
21
  };
22
+ export type MobileSiteNavProps = SiteNavProps & {
23
+ readonly menuLabel?: string;
24
+ };
22
25
  /**
23
26
  * Renders a resolved navigation tree as a `<nav>` landmark with nested lists.
24
27
  *
@@ -28,3 +31,4 @@ export type SiteNavProps = {
28
31
  * where each tree is rendered.
29
32
  */
30
33
  export declare function SiteNav(props: SiteNavProps): import("hono/jsx/jsx-dev-runtime").JSX.Element;
34
+ export declare function MobileSiteNav(props: MobileSiteNavProps): import("hono/jsx/jsx-dev-runtime").JSX.Element;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { NavigationOptions } from "./src/types.js";
2
- export type { SiteNavProps } from "./components/site-nav.js";
3
- export { SiteNav } from "./components/site-nav.js";
2
+ export type { MobileSiteNavProps, SiteNavProps, } from "./components/site-nav.js";
3
+ export { MobileSiteNav, SiteNav } from "./components/site-nav.js";
4
4
  export { buildNavigation, NAVIGATION_PLUGIN_NAME, resolveSiteNavigation, } from "./src/navigation.js";
5
5
  export type { NavigationItem, NavigationOptions, NavigationSource, SiteNavigation, } from "./src/types.js";
6
6
  export declare function navigation(options?: NavigationOptions): import("@riebeckite/core").RiebeckitePlugin<NavigationOptions>;
package/dist/index.js CHANGED
@@ -191,6 +191,13 @@ function SiteNav(props) {
191
191
  }
192
192
  );
193
193
  }
194
+ function MobileSiteNav(props) {
195
+ const { menuLabel = "Menu", ...siteNavProps } = props;
196
+ return /* @__PURE__ */ jsxs("details", { class: "rb-nav__mobile", children: [
197
+ /* @__PURE__ */ jsx("summary", { class: "rb-nav__toggle", children: menuLabel }),
198
+ /* @__PURE__ */ jsx(SiteNav, { ...siteNavProps })
199
+ ] });
200
+ }
194
201
  function NavigationItems(props) {
195
202
  return /* @__PURE__ */ jsx("ul", { class: props.nested ? "rb-nav__list rb-nav__children" : "rb-nav__list", children: props.items.map((item) => /* @__PURE__ */ jsx(
196
203
  NavigationItemView,
@@ -267,6 +274,7 @@ function navigation(options = {}) {
267
274
  }
268
275
  var navigationPlugin = navigation;
269
276
  export {
277
+ MobileSiteNav,
270
278
  NAVIGATION_PLUGIN_NAME,
271
279
  SiteNav,
272
280
  buildNavigation,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/plugin-navigation",
3
- "version": "0.0.27",
3
+ "version": "0.0.28",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,12 +16,13 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "hono": "^4.12.25",
19
- "@riebeckite/core": "0.0.27",
20
- "@riebeckite/ui": "0.0.27"
19
+ "@riebeckite/ui": "0.0.28",
20
+ "@riebeckite/core": "0.0.28"
21
21
  },
22
22
  "devDependencies": {
23
+ "puppeteer": "^25.11.0",
23
24
  "tsx": "^4.22.4",
24
- "@riebeckite/test": "0.0.27"
25
+ "@riebeckite/test": "0.0.28"
25
26
  },
26
27
  "publishConfig": {
27
28
  "access": "public"
@@ -56,6 +57,7 @@
56
57
  ],
57
58
  "scripts": {
58
59
  "build": "node ../../../scripts/build_package.mjs",
59
- "test": "node --import tsx --test \"test/*.test.ts\""
60
+ "test": "node --import tsx --test \"test/*.test.ts\"",
61
+ "test:browser": "node --import tsx --test \"test/browser/*.test.ts\""
60
62
  }
61
63
  }
package/style.css CHANGED
@@ -1,4 +1,8 @@
1
1
  @layer components {
2
+ .rb-nav {
3
+ color: var(--rb-color-ink);
4
+ }
5
+
2
6
  .rb-nav > .rb-nav__list,
3
7
  .rb-nav__children {
4
8
  margin: 0;
@@ -6,7 +10,12 @@
6
10
  }
7
11
 
8
12
  .rb-nav > .rb-nav__list {
13
+ display: flex;
14
+ align-items: center;
15
+ gap: var(--rb-nav-gap, var(--rb-space-3, 1.5rem));
9
16
  padding: 0;
17
+ flex-wrap: var(--rb-nav-list-flex-wrap, nowrap);
18
+ justify-content: var(--rb-nav-list-justify-content, flex-start);
10
19
  }
11
20
 
12
21
  .rb-nav__item {
@@ -19,6 +28,13 @@
19
28
  top: 100%;
20
29
  left: 0;
21
30
  min-width: max-content;
31
+ padding: var(--rb-space-2, 1rem);
32
+ background: var(--rb-color-surface);
33
+ border: 1px solid var(--rb-color-border);
34
+ }
35
+
36
+ .rb-nav__children {
37
+ z-index: 50;
22
38
  }
23
39
 
24
40
  .rb-nav__item:hover > .rb-nav__children,
@@ -26,4 +42,98 @@
26
42
  display: flex;
27
43
  flex-direction: column;
28
44
  }
45
+
46
+ .rb-nav__link {
47
+ display: var(--rb-nav-item-display, inline);
48
+ padding: var(--rb-nav-item-padding, 0);
49
+ color: inherit;
50
+ font-family: var(--rb-nav-item-font-family, inherit);
51
+ font-size: var(--rb-nav-item-font-size, inherit);
52
+ font-weight: var(--rb-nav-item-font-weight, inherit);
53
+ letter-spacing: var(--rb-nav-item-letter-spacing, normal);
54
+ text-decoration: none;
55
+ text-transform: var(--rb-nav-item-text-transform, none);
56
+ }
57
+
58
+ .rb-nav__label {
59
+ display: var(--rb-nav-item-display, inline);
60
+ padding: var(--rb-nav-item-padding, 0);
61
+ font-family: var(--rb-nav-item-font-family, inherit);
62
+ font-size: var(--rb-nav-item-font-size, inherit);
63
+ font-weight: var(--rb-nav-item-font-weight, inherit);
64
+ letter-spacing: var(--rb-nav-item-letter-spacing, normal);
65
+ text-transform: var(--rb-nav-item-text-transform, none);
66
+ }
67
+
68
+ .rb-nav__link:hover,
69
+ .rb-nav__link:focus-visible,
70
+ .rb-nav__link--active {
71
+ color: var(--rb-color-accent);
72
+ }
73
+
74
+ .rb-nav__link:focus-visible,
75
+ .rb-nav__toggle:focus-visible {
76
+ outline: 2px solid var(--rb-color-accent);
77
+ outline-offset: 2px;
78
+ }
79
+
80
+ .rb-nav__mobile {
81
+ position: relative;
82
+ display: none;
83
+ }
84
+
85
+ .rb-nav__toggle {
86
+ cursor: pointer;
87
+ }
88
+
89
+ @media (min-width: 30.001rem) and (max-width: 48rem) {
90
+ .rb-nav > .rb-nav__list {
91
+ flex-wrap: wrap;
92
+ }
93
+ }
94
+
95
+ @media (max-width: 30rem) {
96
+ .rb-nav__mobile {
97
+ display: block;
98
+ }
99
+
100
+ .rb-nav__mobile > .rb-nav {
101
+ position: absolute;
102
+ z-index: 10;
103
+ top: calc(100% + var(--rb-space-2, 1rem));
104
+ right: 0;
105
+ min-width: var(--rb-nav-menu-min-width, 12rem);
106
+ max-width: calc(100vw - 2rem);
107
+ padding: var(--rb-space-3, 1.5rem);
108
+ background: var(--rb-color-surface);
109
+ border: 1px solid var(--rb-color-border);
110
+ box-shadow: 0 4px 12px
111
+ color-mix(in oklab, var(--rb-color-ink) 14%, transparent);
112
+ }
113
+
114
+ .rb-nav__mobile .rb-nav__list,
115
+ .rb-nav__mobile .rb-nav__children {
116
+ display: flex;
117
+ flex-direction: column;
118
+ align-items: flex-start;
119
+ gap: var(--rb-space-2, 1rem);
120
+ }
121
+
122
+ .rb-nav__mobile .rb-nav__list {
123
+ padding: 0;
124
+ }
125
+
126
+ .rb-nav__mobile .rb-nav__children {
127
+ position: static;
128
+ margin-top: var(--rb-space-2, 1rem);
129
+ padding: 0;
130
+ background: transparent;
131
+ border: 0;
132
+ }
133
+
134
+ .rb-nav__mobile .rb-nav__link,
135
+ .rb-nav__mobile .rb-nav__label {
136
+ overflow-wrap: anywhere;
137
+ }
138
+ }
29
139
  }