@vantagecompute/docusaurus-theme 0.4.8 → 0.5.0
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 +38 -37
- package/lib/index.cjs +26 -57
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +19 -54
- package/lib/index.d.cts.map +1 -1
- package/lib/options.cjs +102 -0
- package/lib/options.cjs.map +1 -0
- package/lib/options.d.cts +46 -0
- package/lib/options.d.cts.map +1 -0
- package/package.json +2 -1
- package/src/css/custom.css +270 -154
- package/src/index.cts +50 -74
- package/src/options.cts +143 -0
- package/src/theme/Footer/index.js +9 -0
- package/src/theme/MDXComponents/TableScroll.jsx +19 -0
- package/src/theme/MDXComponents/index.js +17 -0
- package/src/theme/Navbar/Content/index.jsx +91 -0
- package/src/theme/Navbar/Content/styles.module.css +6 -0
- package/src/theme/Navbar/Logo/index.jsx +28 -25
- package/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.jsx +28 -0
- package/src/theme/Navbar/SiteActions/index.jsx +11 -0
- package/src/theme/Navbar/useVantageNavbar.js +48 -0
package/src/index.cts
CHANGED
|
@@ -1,8 +1,38 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import {
|
|
3
|
-
import type { Plugin
|
|
2
|
+
import {execSync} from 'node:child_process';
|
|
3
|
+
import type {LoadContext, OptionValidationContext, Plugin} from '@docusaurus/types';
|
|
4
|
+
import {
|
|
5
|
+
LOGO_HREF,
|
|
6
|
+
resolveNavbarVariant,
|
|
7
|
+
validateVantageThemeOptions,
|
|
8
|
+
type ResolvedVantageThemeOptions,
|
|
9
|
+
type VantageThemeOptions,
|
|
10
|
+
} from './options.cjs';
|
|
11
|
+
|
|
12
|
+
export type {NavbarLink, NavbarVariant, VantageThemeOptions} from './options.cjs';
|
|
13
|
+
export {LOGO_HREF, MAX_NAVBAR_LINKS, resolveNavbarVariant} from './options.cjs';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Shape of the global data the theme's client components read through
|
|
17
|
+
* `usePluginData('@vantagecompute/docusaurus-theme')`.
|
|
18
|
+
*/
|
|
19
|
+
export interface VantageThemeGlobalData {
|
|
20
|
+
variant: 'public' | 'developer';
|
|
21
|
+
logoHref: string;
|
|
22
|
+
navbarLinks: ResolvedVantageThemeOptions['navbarLinks'];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default function themeVantage(
|
|
26
|
+
context: LoadContext,
|
|
27
|
+
options: ResolvedVantageThemeOptions,
|
|
28
|
+
): Plugin {
|
|
29
|
+
const variant = resolveNavbarVariant(context.baseUrl);
|
|
30
|
+
const globalData: VantageThemeGlobalData = {
|
|
31
|
+
variant,
|
|
32
|
+
logoHref: LOGO_HREF[variant],
|
|
33
|
+
navbarLinks: options.navbarLinks,
|
|
34
|
+
};
|
|
4
35
|
|
|
5
|
-
export default function themeVantage(): Plugin {
|
|
6
36
|
return {
|
|
7
37
|
name: '@vantagecompute/docusaurus-theme',
|
|
8
38
|
|
|
@@ -17,9 +47,26 @@ export default function themeVantage(): Plugin {
|
|
|
17
47
|
getClientModules() {
|
|
18
48
|
return [path.resolve(__dirname, '../src/css/custom.css')];
|
|
19
49
|
},
|
|
50
|
+
|
|
51
|
+
// The navbar variant and the external buttons reach the client this way.
|
|
52
|
+
// Nothing in themeConfig.navbar is read by the theme's components.
|
|
53
|
+
contentLoaded({actions}) {
|
|
54
|
+
actions.setGlobalData(globalData);
|
|
55
|
+
},
|
|
20
56
|
};
|
|
21
57
|
}
|
|
22
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Docusaurus calls this before the plugin factory. Hand-rolled rather than Joi
|
|
61
|
+
* so the package carries no validation dependency; see src/options.cts.
|
|
62
|
+
*/
|
|
63
|
+
export function validateOptions({
|
|
64
|
+
options,
|
|
65
|
+
}: OptionValidationContext<VantageThemeOptions | undefined, ResolvedVantageThemeOptions>):
|
|
66
|
+
ResolvedVantageThemeOptions {
|
|
67
|
+
return validateVantageThemeOptions(options);
|
|
68
|
+
}
|
|
69
|
+
|
|
23
70
|
/**
|
|
24
71
|
* Returns the absolute path to this package's static directory.
|
|
25
72
|
* Add this to your `staticDirectories` in docusaurus.config.js:
|
|
@@ -52,74 +99,3 @@ export function getProjectVersion(): string {
|
|
|
52
99
|
|
|
53
100
|
// Re-export the rehype utility (plain JS, lives in src/utils/)
|
|
54
101
|
export const rehypeTabsTransform = require(path.resolve(__dirname, '../src/utils/rehypeTabsTransform'));
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Shape of a Docusaurus navbar or footer logo entry.
|
|
58
|
-
*/
|
|
59
|
-
export interface ThemeLogo {
|
|
60
|
-
alt: string;
|
|
61
|
-
src: string;
|
|
62
|
-
srcDark?: string;
|
|
63
|
-
href: string;
|
|
64
|
-
target?: string;
|
|
65
|
-
width?: number;
|
|
66
|
-
height?: number;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* The Vantage colour brand mark, as a path relative to a served static
|
|
71
|
-
* directory. It resolves once `staticDir` is in `staticDirectories`; no site
|
|
72
|
-
* needs its own copy of the SVG.
|
|
73
|
-
*/
|
|
74
|
-
const VANTAGE_LOGO_SRC = 'img/vantage-logo-color.svg';
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Navbar logo for a Vantage documentation site.
|
|
78
|
-
*
|
|
79
|
-
* ```js
|
|
80
|
-
* const { navbarLogo } = require('@vantagecompute/docusaurus-theme');
|
|
81
|
-
* themeConfig: { navbar: { title: 'v8x', logo: navbarLogo, items: [...] } }
|
|
82
|
-
* ```
|
|
83
|
-
*
|
|
84
|
-
* Deliberately has no `srcDark`. The single colour mark is drawn to read on
|
|
85
|
-
* both colour modes, and a second asset would only be a second thing to keep
|
|
86
|
-
* in sync.
|
|
87
|
-
*
|
|
88
|
-
* `href` points at the docs hub rather than the marketing site: from a spoke's
|
|
89
|
-
* documentation the useful "home" is the rest of the documentation. `target`
|
|
90
|
-
* is `_self` so that jump replaces the tab instead of opening a new one.
|
|
91
|
-
*
|
|
92
|
-
* Override by spreading, never by mutating -- the object is shared by every
|
|
93
|
-
* site in the process:
|
|
94
|
-
*
|
|
95
|
-
* ```js
|
|
96
|
-
* logo: { ...navbarLogo, href: 'https://docs.vantagecompute.ai/developer/' }
|
|
97
|
-
* ```
|
|
98
|
-
*
|
|
99
|
-
* Omit `logo` entirely to render no navbar logo.
|
|
100
|
-
*/
|
|
101
|
-
export const navbarLogo: ThemeLogo = {
|
|
102
|
-
alt: 'Vantage Compute Logo',
|
|
103
|
-
src: VANTAGE_LOGO_SRC,
|
|
104
|
-
href: 'https://docs.vantagecompute.ai',
|
|
105
|
-
target: '_self',
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Footer logo for a Vantage documentation site.
|
|
110
|
-
*
|
|
111
|
-
* ```js
|
|
112
|
-
* const { footerLogo } = require('@vantagecompute/docusaurus-theme');
|
|
113
|
-
* themeConfig: { footer: { style: 'dark', logo: footerLogo, links: [...] } }
|
|
114
|
-
* ```
|
|
115
|
-
*
|
|
116
|
-
* Same mark as {@link navbarLogo}, but `href` points at the marketing site:
|
|
117
|
-
* the footer is where a reader who has finished reading looks for the company.
|
|
118
|
-
*
|
|
119
|
-
* Override by spreading; omit `logo` to render no footer logo.
|
|
120
|
-
*/
|
|
121
|
-
export const footerLogo: ThemeLogo = {
|
|
122
|
-
alt: 'Vantage Compute Logo',
|
|
123
|
-
src: VANTAGE_LOGO_SRC,
|
|
124
|
-
href: 'https://vantagecompute.ai',
|
|
125
|
-
};
|
package/src/options.cts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme options and the navbar variant rule. Pure functions with no Docusaurus
|
|
3
|
+
* imports, so they are tested directly against the compiled output.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type NavbarVariant = 'public' | 'developer';
|
|
7
|
+
|
|
8
|
+
/** One external button in the developer navbar. Nothing else is configurable. */
|
|
9
|
+
export interface NavbarLink {
|
|
10
|
+
label: string;
|
|
11
|
+
url: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** What a site may pass in `themes: [['@vantagecompute/docusaurus-theme', {...}]]`. */
|
|
15
|
+
export interface VantageThemeOptions {
|
|
16
|
+
/** External buttons, at most {@link MAX_NAVBAR_LINKS}. Rendered by the developer navbar only. */
|
|
17
|
+
navbarLinks?: NavbarLink[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Options after validation. `id` is Docusaurus's plugin-instance id. When a
|
|
22
|
+
* plugin exports validateOptions, Docusaurus trusts the returned object to
|
|
23
|
+
* carry it (its own Joi path adds one), and names the plugin's generated data
|
|
24
|
+
* directory after it. Leaving it out crashes the build in path.join.
|
|
25
|
+
*/
|
|
26
|
+
export interface ResolvedVantageThemeOptions {
|
|
27
|
+
id: string;
|
|
28
|
+
navbarLinks: NavbarLink[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const DEFAULT_PLUGIN_ID = 'default';
|
|
32
|
+
|
|
33
|
+
/** Two is GitHub plus one registry (PyPI, npm, ...). More than that is a nav, and navs drift. */
|
|
34
|
+
export const MAX_NAVBAR_LINKS = 2;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Where the brand mark links, per variant. Baked in on purpose: a site cannot
|
|
38
|
+
* point its logo anywhere else, which is what keeps the hub consistent.
|
|
39
|
+
*/
|
|
40
|
+
export const LOGO_HREF: Record<NavbarVariant, string> = {
|
|
41
|
+
public: 'https://docs.vantagecompute.ai/',
|
|
42
|
+
developer: 'https://docs.vantagecompute.ai/developer/',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Every site published under /developer/ (the developer overview and every
|
|
47
|
+
* spoke) gets the developer navbar. Everything else gets the public one.
|
|
48
|
+
* Docusaurus normalises baseUrl to a leading and trailing slash before the
|
|
49
|
+
* plugin sees it.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveNavbarVariant(baseUrl: string): NavbarVariant {
|
|
52
|
+
return baseUrl.startsWith('/developer/') ? 'developer' : 'public';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const PREFIX = '[@vantagecompute/docusaurus-theme]';
|
|
56
|
+
|
|
57
|
+
function fail(message: string): never {
|
|
58
|
+
throw new Error(`${PREFIX} ${message}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
62
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function validateLink(value: unknown, index: number): NavbarLink {
|
|
66
|
+
const where = `navbarLinks[${index}]`;
|
|
67
|
+
if (!isPlainObject(value)) {
|
|
68
|
+
fail(`${where} must be an object with "label" and "url".`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const extra = Object.keys(value).filter((key) => key !== 'label' && key !== 'url');
|
|
72
|
+
if (extra.length > 0) {
|
|
73
|
+
fail(
|
|
74
|
+
`${where} has unsupported propert${extra.length === 1 ? 'y' : 'ies'} ` +
|
|
75
|
+
`${extra.map((k) => `"${k}"`).join(', ')}. Only "label" and "url" are ` +
|
|
76
|
+
`accepted; the icon, external-link marker and rel attributes come from the theme.`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const {label, url} = value;
|
|
81
|
+
if (typeof label !== 'string' || label.trim() === '') {
|
|
82
|
+
fail(`${where}.label must be a non-empty string.`);
|
|
83
|
+
}
|
|
84
|
+
if (typeof url !== 'string' || url.trim() === '') {
|
|
85
|
+
fail(`${where}.url must be a non-empty string.`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let parsed: URL;
|
|
89
|
+
try {
|
|
90
|
+
parsed = new URL(url);
|
|
91
|
+
} catch {
|
|
92
|
+
return fail(`${where}.url must be an absolute http(s) URL, got "${url}".`);
|
|
93
|
+
}
|
|
94
|
+
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
|
|
95
|
+
fail(`${where}.url must be an absolute http(s) URL, got "${url}".`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {label: label.trim(), url};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Validate and normalise the theme options. Throws with a message that names
|
|
103
|
+
* the offending key, so a misconfigured spoke fails its build instead of
|
|
104
|
+
* quietly rendering something off-convention.
|
|
105
|
+
*/
|
|
106
|
+
export function validateVantageThemeOptions(options: unknown): ResolvedVantageThemeOptions {
|
|
107
|
+
if (options === undefined || options === null) {
|
|
108
|
+
return {id: DEFAULT_PLUGIN_ID, navbarLinks: []};
|
|
109
|
+
}
|
|
110
|
+
if (!isPlainObject(options)) {
|
|
111
|
+
fail('theme options must be an object.');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const {navbarLinks, id, ...unknown} = options;
|
|
115
|
+
const unknownKeys = Object.keys(unknown);
|
|
116
|
+
if (unknownKeys.length > 0) {
|
|
117
|
+
fail(
|
|
118
|
+
`unknown option${unknownKeys.length === 1 ? '' : 's'} ` +
|
|
119
|
+
`${unknownKeys.map((k) => `"${k}"`).join(', ')}. The only option is "navbarLinks".`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const resolved: ResolvedVantageThemeOptions = {
|
|
124
|
+
id: typeof id === 'string' ? id : DEFAULT_PLUGIN_ID,
|
|
125
|
+
navbarLinks: [],
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
if (navbarLinks === undefined) {
|
|
129
|
+
return resolved;
|
|
130
|
+
}
|
|
131
|
+
if (!Array.isArray(navbarLinks)) {
|
|
132
|
+
fail('"navbarLinks" must be an array of {label, url} objects.');
|
|
133
|
+
}
|
|
134
|
+
if (navbarLinks.length > MAX_NAVBAR_LINKS) {
|
|
135
|
+
fail(
|
|
136
|
+
`"navbarLinks" allows at most ${MAX_NAVBAR_LINKS} entries, got ${navbarLinks.length}. ` +
|
|
137
|
+
`GitHub plus one package registry is the intended use.`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
resolved.navbarLinks = navbarLinks.map(validateLink);
|
|
142
|
+
return resolved;
|
|
143
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* No Vantage documentation site renders a footer. The collapse-sidebar control
|
|
3
|
+
* already frames the bottom of the screen, and the links a footer would carry
|
|
4
|
+
* are the navbar's external buttons. A site that still declares
|
|
5
|
+
* themeConfig.footer builds fine and renders nothing.
|
|
6
|
+
*/
|
|
7
|
+
export default function Footer() {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A markdown table inside a horizontal scroll region.
|
|
3
|
+
*
|
|
4
|
+
* The theme frames tables with a border and a radius. Doing that on the table
|
|
5
|
+
* itself needed `overflow: hidden`, which removed the `display: block;
|
|
6
|
+
* overflow-x: auto` Docusaurus ships for wide tables, and on a 345px phone
|
|
7
|
+
* column a four-column reference table squeezed to 61px columns and 171px
|
|
8
|
+
* rows. The wrapper carries the frame now (see `.table-scroll` in
|
|
9
|
+
* src/css/custom.css); the table keeps its natural width and scrolls.
|
|
10
|
+
*
|
|
11
|
+
* `role="region"` plus `tabIndex` so a keyboard user can reach and scroll it.
|
|
12
|
+
*/
|
|
13
|
+
export default function TableScroll(props) {
|
|
14
|
+
return (
|
|
15
|
+
<div className="table-scroll" role="region" aria-label="Table, scrolls horizontally" tabIndex={0}>
|
|
16
|
+
<table {...props} />
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Routes every markdown `table` through TableScroll. Docusaurus's own map has
|
|
2
|
+
// no `table` entry, so this adds one rather than replacing anything.
|
|
3
|
+
//
|
|
4
|
+
// @theme-init, not @theme-original: this file ships inside a theme package that
|
|
5
|
+
// sits in the theme stack, so @theme-original/MDXComponents would resolve back
|
|
6
|
+
// to this same module and recurse. See src/theme/Navbar/Logo for the same note.
|
|
7
|
+
//
|
|
8
|
+
// A site that already wraps `table` itself (vantage-docs did, before this
|
|
9
|
+
// shipped) must drop its own wrapper, or every table renders in two scroll
|
|
10
|
+
// regions. MIGRATION.md, Part 3.
|
|
11
|
+
import MDXComponents from '@theme-init/MDXComponents';
|
|
12
|
+
import TableScroll from './TableScroll';
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
...MDXComponents,
|
|
16
|
+
table: TableScroll,
|
|
17
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import {ErrorCauseBoundary, ThemeClassNames} from '@docusaurus/theme-common';
|
|
4
|
+
import {useNavbarMobileSidebar} from '@docusaurus/theme-common/internal';
|
|
5
|
+
import NavbarItem from '@theme/NavbarItem';
|
|
6
|
+
import NavbarColorModeToggle from '@theme/Navbar/ColorModeToggle';
|
|
7
|
+
import SearchBar from '@theme/SearchBar';
|
|
8
|
+
import NavbarMobileSidebarToggle from '@theme/Navbar/MobileSidebar/Toggle';
|
|
9
|
+
import NavbarLogo from '@theme/Navbar/Logo';
|
|
10
|
+
import NavbarSearch from '@theme/Navbar/Search';
|
|
11
|
+
import NavbarSiteActions from '@theme/Navbar/SiteActions';
|
|
12
|
+
import {toNavbarItems, useVantageNavbar} from '../useVantageNavbar';
|
|
13
|
+
|
|
14
|
+
import styles from './styles.module.css';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The navbar, replacing theme-classic's Navbar/Content.
|
|
18
|
+
*
|
|
19
|
+
* Two fixed variants, chosen by the theme from the site's baseUrl:
|
|
20
|
+
*
|
|
21
|
+
* public logo | search, SiteActions slot, colour-mode toggle
|
|
22
|
+
* developer logo + centred title and version | external buttons, toggle
|
|
23
|
+
*
|
|
24
|
+
* themeConfig.navbar.items is never read. A site that still declares items
|
|
25
|
+
* gets no error and no rendering; the convention is the theme's to hold.
|
|
26
|
+
*/
|
|
27
|
+
function ExternalLinks({items}) {
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
{items.map((item, i) => (
|
|
31
|
+
<ErrorCauseBoundary
|
|
32
|
+
key={i}
|
|
33
|
+
onError={(error) =>
|
|
34
|
+
new Error(
|
|
35
|
+
`A theme navbar link failed to render: ${JSON.stringify(item)}`,
|
|
36
|
+
{cause: error},
|
|
37
|
+
)
|
|
38
|
+
}>
|
|
39
|
+
<NavbarItem {...item} />
|
|
40
|
+
</ErrorCauseBoundary>
|
|
41
|
+
))}
|
|
42
|
+
</>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function NavbarContentLayout({left, right}) {
|
|
47
|
+
return (
|
|
48
|
+
<div className="navbar__inner">
|
|
49
|
+
<div className={clsx(ThemeClassNames.layout.navbar.containerLeft, 'navbar__items')}>
|
|
50
|
+
{left}
|
|
51
|
+
</div>
|
|
52
|
+
<div
|
|
53
|
+
className={clsx(
|
|
54
|
+
ThemeClassNames.layout.navbar.containerRight,
|
|
55
|
+
'navbar__items navbar__items--right',
|
|
56
|
+
)}>
|
|
57
|
+
{right}
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default function NavbarContent() {
|
|
64
|
+
const mobileSidebar = useNavbarMobileSidebar();
|
|
65
|
+
const {variant, links} = useVantageNavbar();
|
|
66
|
+
|
|
67
|
+
const left = (
|
|
68
|
+
<>
|
|
69
|
+
{!mobileSidebar.disabled && <NavbarMobileSidebarToggle />}
|
|
70
|
+
<NavbarLogo />
|
|
71
|
+
</>
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const right =
|
|
75
|
+
variant === 'developer' ? (
|
|
76
|
+
<>
|
|
77
|
+
<ExternalLinks items={toNavbarItems(links)} />
|
|
78
|
+
<NavbarColorModeToggle className={styles.colorModeToggle} />
|
|
79
|
+
</>
|
|
80
|
+
) : (
|
|
81
|
+
<>
|
|
82
|
+
<NavbarSearch>
|
|
83
|
+
<SearchBar />
|
|
84
|
+
</NavbarSearch>
|
|
85
|
+
<NavbarSiteActions />
|
|
86
|
+
<NavbarColorModeToggle className={styles.colorModeToggle} />
|
|
87
|
+
</>
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return <NavbarContentLayout left={left} right={right} />;
|
|
91
|
+
}
|
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import useBaseUrl from '@docusaurus/useBaseUrl';
|
|
3
|
+
import {useVantageNavbar} from '../useVantageNavbar';
|
|
4
|
+
|
|
5
|
+
// The one colour mark reads on both colour modes, so there is no srcDark and
|
|
6
|
+
// no second asset to keep in sync. Resolves through staticDir, which every
|
|
7
|
+
// Vantage site lists in staticDirectories.
|
|
8
|
+
const LOGO_SRC = 'img/vantage-logo-color.svg';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* The brand link, the centred title and the version badge.
|
|
12
|
+
*
|
|
13
|
+
* Replaces theme-classic's Logo outright instead of wrapping it, because the
|
|
14
|
+
* href is not the site's to choose: the theme bakes it per variant (the docs
|
|
15
|
+
* root for the public navbar, the developer overview for the developer one).
|
|
16
|
+
* A plain anchor rather than @docusaurus/Link because the jump crosses SPA
|
|
17
|
+
* boundaries and should be a full navigation. Same tab: command-click covers
|
|
18
|
+
* "open in a new tab".
|
|
13
19
|
*
|
|
14
|
-
* The
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
20
|
+
* The markup mirrors theme-classic's (navbar__brand > navbar__logo > img,
|
|
21
|
+
* plus b.navbar__title) so Infima's and this theme's CSS keep applying. On
|
|
22
|
+
* desktop the in-brand title is hidden by CSS and re-rendered centred below,
|
|
23
|
+
* which is what lets the version badge sit beside it.
|
|
18
24
|
*/
|
|
19
|
-
export default function
|
|
20
|
-
const {
|
|
21
|
-
|
|
22
|
-
const raw = siteConfig.customFields?.projectVersion;
|
|
23
|
-
const version = raw
|
|
24
|
-
? String(raw).startsWith('v')
|
|
25
|
-
? String(raw)
|
|
26
|
-
: `v${raw}`
|
|
27
|
-
: null;
|
|
28
|
-
|
|
29
|
-
const title = siteConfig.themeConfig?.navbar?.title;
|
|
25
|
+
export default function NavbarLogo() {
|
|
26
|
+
const {logoHref, title, version} = useVantageNavbar();
|
|
27
|
+
const src = useBaseUrl(LOGO_SRC);
|
|
30
28
|
|
|
31
29
|
return (
|
|
32
30
|
<>
|
|
33
|
-
<
|
|
31
|
+
<a className="navbar__brand" href={logoHref}>
|
|
32
|
+
<div className="navbar__logo">
|
|
33
|
+
<img src={src} alt="Vantage Compute Logo" />
|
|
34
|
+
</div>
|
|
35
|
+
{title && <b className="navbar__title text--truncate">{title}</b>}
|
|
36
|
+
</a>
|
|
34
37
|
{(title || version) && (
|
|
35
38
|
<div className="navbar__center-title">
|
|
36
39
|
{title && <span className="navbar__center-title-text">{title}</span>}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {useNavbarMobileSidebar} from '@docusaurus/theme-common/internal';
|
|
3
|
+
import NavbarItem from '@theme/NavbarItem';
|
|
4
|
+
import {toNavbarItems, useVantageNavbar} from '../../useVantageNavbar';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The primary panel of the mobile drawer. theme-classic fills it from
|
|
8
|
+
* themeConfig.navbar.items; this theme fills it from the same external
|
|
9
|
+
* buttons the developer navbar shows. The public navbar has nothing to put
|
|
10
|
+
* here (search and the site's actions stay in the bar), so the panel is empty
|
|
11
|
+
* and the drawer opens straight onto the docs sidebar.
|
|
12
|
+
*/
|
|
13
|
+
export default function NavbarMobilePrimaryMenu() {
|
|
14
|
+
const mobileSidebar = useNavbarMobileSidebar();
|
|
15
|
+
const {variant, links} = useVantageNavbar();
|
|
16
|
+
|
|
17
|
+
if (variant !== 'developer' || links.length === 0) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<ul className="menu__list">
|
|
23
|
+
{toNavbarItems(links).map((item, i) => (
|
|
24
|
+
<NavbarItem mobile {...item} onClick={() => mobileSidebar.toggle()} key={i} />
|
|
25
|
+
))}
|
|
26
|
+
</ul>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A slot in the public navbar, between search and the colour-mode toggle.
|
|
3
|
+
* Empty here. The main docs site overrides it in its own src/theme/ to render
|
|
4
|
+
* its Ask AI button; that component talks to the Vantage AI backend and does
|
|
5
|
+
* not belong in a theme package.
|
|
6
|
+
*
|
|
7
|
+
* The developer navbar does not render this slot.
|
|
8
|
+
*/
|
|
9
|
+
export default function NavbarSiteActions() {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
2
|
+
import {usePluginData} from '@docusaurus/useGlobalData';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Everything the theme's navbar components need, in one place. The variant,
|
|
6
|
+
* the brand-link href and the external buttons come from the theme's Node
|
|
7
|
+
* side (setGlobalData in lib/index.cjs). The title and version come from the
|
|
8
|
+
* site config. themeConfig.navbar is deliberately never read.
|
|
9
|
+
*/
|
|
10
|
+
export function useVantageNavbar() {
|
|
11
|
+
const {siteConfig} = useDocusaurusContext();
|
|
12
|
+
const {variant, logoHref, navbarLinks} = usePluginData('@vantagecompute/docusaurus-theme');
|
|
13
|
+
|
|
14
|
+
const raw = siteConfig.customFields?.projectVersion;
|
|
15
|
+
const version = raw
|
|
16
|
+
? String(raw).startsWith('v')
|
|
17
|
+
? String(raw)
|
|
18
|
+
: `v${raw}`
|
|
19
|
+
: null;
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
variant,
|
|
23
|
+
logoHref,
|
|
24
|
+
links: navbarLinks,
|
|
25
|
+
// The developer navbar names the project beside its version, which is
|
|
26
|
+
// how a reader confirms they are on the version they think they are.
|
|
27
|
+
// The public navbar is logo-only.
|
|
28
|
+
title: variant === 'developer' ? siteConfig.title : null,
|
|
29
|
+
version,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Map the validated {label, url} links onto theme-classic NavbarItem props.
|
|
35
|
+
* External destinations open in a new tab, the accepted convention for
|
|
36
|
+
* leaving a site. NavbarNavLink appends the external-link icon on its own
|
|
37
|
+
* because href is external and label is set.
|
|
38
|
+
*/
|
|
39
|
+
export function toNavbarItems(links) {
|
|
40
|
+
return links.map((link) => ({
|
|
41
|
+
label: link.label,
|
|
42
|
+
href: link.url,
|
|
43
|
+
position: 'right',
|
|
44
|
+
target: '_blank',
|
|
45
|
+
rel: 'noopener noreferrer',
|
|
46
|
+
className: 'navbar__external-link',
|
|
47
|
+
}));
|
|
48
|
+
}
|