@netfoundry/docusaurus-theme 0.9.0 → 0.10.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/css/layout.css +37 -0
- package/css/product-picker.css +36 -8
- package/css/theme.css +51 -20
- package/css/vars.css +1 -0
- package/dist/css/layout.css +37 -0
- package/dist/css/product-picker.css +36 -8
- package/dist/css/theme.css +51 -20
- package/dist/css/vars.css +1 -0
- package/dist/src/components/NetFoundryFooter/NetFoundryFooter.d.ts.map +1 -1
- package/dist/src/components/NetFoundryFooter/NetFoundryFooter.js +3 -2
- package/dist/src/components/NetFoundryFooter/NetFoundryFooter.js.map +1 -1
- package/dist/src/components/NetFoundryFooter/styles.module.css +1 -1
- package/dist/src/components/icons/DiscourseIcon.d.ts +8 -0
- package/dist/src/components/icons/DiscourseIcon.d.ts.map +1 -0
- package/dist/src/components/icons/DiscourseIcon.js +5 -0
- package/dist/src/components/icons/DiscourseIcon.js.map +1 -0
- package/dist/src/components/icons/GitHubIcon.d.ts +8 -0
- package/dist/src/components/icons/GitHubIcon.d.ts.map +1 -0
- package/dist/src/components/icons/GitHubIcon.js +5 -0
- package/dist/src/components/icons/GitHubIcon.js.map +1 -0
- package/dist/src/components/icons/XIcon.d.ts +8 -0
- package/dist/src/components/icons/XIcon.d.ts.map +1 -0
- package/dist/src/components/icons/XIcon.js +5 -0
- package/dist/src/components/icons/XIcon.js.map +1 -0
- package/dist/src/components/icons/YouTubeIcon.d.ts +8 -0
- package/dist/src/components/icons/YouTubeIcon.d.ts.map +1 -0
- package/dist/src/components/icons/YouTubeIcon.js +5 -0
- package/dist/src/components/icons/YouTubeIcon.js.map +1 -0
- package/dist/src/components/icons/index.d.ts +5 -0
- package/dist/src/components/icons/index.d.ts.map +1 -0
- package/dist/src/components/icons/index.js +5 -0
- package/dist/src/components/icons/index.js.map +1 -0
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +1 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -1
- package/dist/theme/NavbarItem/ComponentTypes.d.ts +4 -0
- package/dist/theme/NavbarItem/ComponentTypes.d.ts.map +1 -1
- package/dist/theme/NavbarItem/ComponentTypes.js +4 -0
- package/dist/theme/NavbarItem/ComponentTypes.js.map +1 -1
- package/dist/theme/NavbarItem/NavbarPicker.d.ts +13 -0
- package/dist/theme/NavbarItem/NavbarPicker.d.ts.map +1 -0
- package/dist/theme/NavbarItem/NavbarPicker.js +59 -0
- package/dist/theme/NavbarItem/NavbarPicker.js.map +1 -0
- package/dist/theme/NavbarItem/types/IconLinks/index.d.ts +4 -0
- package/dist/theme/NavbarItem/types/IconLinks/index.d.ts.map +1 -0
- package/dist/theme/NavbarItem/types/IconLinks/index.js +22 -0
- package/dist/theme/NavbarItem/types/IconLinks/index.js.map +1 -0
- package/dist/theme/NavbarItem/types/ProductPicker/index.d.ts.map +1 -1
- package/dist/theme/NavbarItem/types/ProductPicker/index.js +3 -49
- package/dist/theme/NavbarItem/types/ProductPicker/index.js.map +1 -1
- package/dist/theme/NavbarItem/types/ResourcesPicker/index.d.ts +8 -0
- package/dist/theme/NavbarItem/types/ResourcesPicker/index.d.ts.map +1 -0
- package/dist/theme/NavbarItem/types/ResourcesPicker/index.js +30 -0
- package/dist/theme/NavbarItem/types/ResourcesPicker/index.js.map +1 -0
- package/package.json +1 -1
- package/theme/NavbarItem/ComponentTypes.tsx +4 -0
- package/theme/NavbarItem/NavbarPicker.tsx +94 -0
- package/theme/NavbarItem/types/IconLinks/index.tsx +35 -0
- package/theme/NavbarItem/types/ProductPicker/index.tsx +88 -154
- package/theme/NavbarItem/types/ResourcesPicker/index.tsx +88 -0
- package/css/.claude/settings.local.json +0 -12
|
@@ -1,154 +1,88 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import Link from '@docusaurus/Link';
|
|
3
|
-
import clsx from 'clsx';
|
|
4
|
-
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
5
|
-
import {useThemeConfig} from '@docusaurus/theme-common';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
{ label: '
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{ label: '
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
{ label: '
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const onOtherOpen = (e: any) => {
|
|
90
|
-
if (e.detail.label !== label) close();
|
|
91
|
-
};
|
|
92
|
-
window.addEventListener('nf-picker:open', onOtherOpen);
|
|
93
|
-
return () => window.removeEventListener('nf-picker:open', onOtherOpen);
|
|
94
|
-
}, [label, close]);
|
|
95
|
-
|
|
96
|
-
const handleTriggerEnter = useCallback(() => {
|
|
97
|
-
hasEnteredPanel.current = false;
|
|
98
|
-
window.dispatchEvent(new CustomEvent('nf-picker:open', {detail: {label}}));
|
|
99
|
-
setOpen(true);
|
|
100
|
-
}, [label]);
|
|
101
|
-
|
|
102
|
-
// Stay open until user enters the panel — no timer
|
|
103
|
-
const handleTriggerLeave = useCallback(() => {}, []);
|
|
104
|
-
|
|
105
|
-
const handlePanelEnter = useCallback(() => {
|
|
106
|
-
hasEnteredPanel.current = true;
|
|
107
|
-
}, []);
|
|
108
|
-
|
|
109
|
-
const handlePanelLeave = useCallback(() => {
|
|
110
|
-
if (hasEnteredPanel.current) close();
|
|
111
|
-
}, [close]);
|
|
112
|
-
|
|
113
|
-
return (
|
|
114
|
-
<div
|
|
115
|
-
ref={wrapRef}
|
|
116
|
-
className={clsx('navbar__item', {'nf-picker--open': open})}>
|
|
117
|
-
<a
|
|
118
|
-
role="button"
|
|
119
|
-
href="#"
|
|
120
|
-
aria-haspopup="true"
|
|
121
|
-
aria-expanded={open}
|
|
122
|
-
className={clsx('navbar__link', 'nf-picker-trigger', className)}
|
|
123
|
-
onMouseEnter={handleTriggerEnter}
|
|
124
|
-
onMouseLeave={handleTriggerLeave}
|
|
125
|
-
onClick={e => { e.preventDefault(); setOpen(o => !o); }}
|
|
126
|
-
onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); setOpen(o => !o); } }}>
|
|
127
|
-
{label}
|
|
128
|
-
</a>
|
|
129
|
-
<div
|
|
130
|
-
className={clsx('nf-picker-panel', {'nf-picker-panel--hidden': !open})}
|
|
131
|
-
onMouseDown={e => e.stopPropagation()}
|
|
132
|
-
onMouseEnter={handlePanelEnter}
|
|
133
|
-
onMouseLeave={handlePanelLeave}>
|
|
134
|
-
<div className="picker-content">
|
|
135
|
-
{resolvedColumns.map((col, i) => (
|
|
136
|
-
<div key={i} className="picker-column">
|
|
137
|
-
<span className={clsx('picker-header', col.headerClass)}>{col.header}</span>
|
|
138
|
-
{col.links.map((link, j) => (
|
|
139
|
-
<Link key={j} to={link.to} className="picker-link">
|
|
140
|
-
{link.logo && <img src={link.logo} className={clsx('picker-logo', link.logoDark && 'picker-logo--light')} alt="" />}
|
|
141
|
-
{link.logoDark && <img src={link.logoDark} className="picker-logo picker-logo--dark" alt="" />}
|
|
142
|
-
<div className="picker-text">
|
|
143
|
-
<strong>{link.label}</strong>
|
|
144
|
-
{link.description && <span>{link.description}</span>}
|
|
145
|
-
</div>
|
|
146
|
-
</Link>
|
|
147
|
-
))}
|
|
148
|
-
</div>
|
|
149
|
-
))}
|
|
150
|
-
</div>
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
);
|
|
154
|
-
}
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Link from '@docusaurus/Link';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
5
|
+
import {useThemeConfig} from '@docusaurus/theme-common';
|
|
6
|
+
import NavbarPicker from '../../NavbarPicker';
|
|
7
|
+
|
|
8
|
+
export type PickerLink = {
|
|
9
|
+
label: string;
|
|
10
|
+
to: string;
|
|
11
|
+
logo?: string;
|
|
12
|
+
logoDark?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type PickerColumn = {
|
|
17
|
+
header: string;
|
|
18
|
+
headerClass?: string;
|
|
19
|
+
links: PickerLink[];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type Props = {
|
|
23
|
+
label?: string;
|
|
24
|
+
position?: 'left' | 'right';
|
|
25
|
+
className?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const HEADER_CLASSES = ['picker-header--nf-tertiary', 'picker-header--nf-secondary', 'picker-header--nf-primary'];
|
|
29
|
+
const NF_LOGO_DEFAULT = 'https://raw.githubusercontent.com/netfoundry/branding/refs/heads/main/images/svg/icon/netfoundry-icon-color.svg';
|
|
30
|
+
|
|
31
|
+
const buildDefaultColumns = (img: string, consoleLogo: string): PickerColumn[] => [
|
|
32
|
+
{
|
|
33
|
+
header: 'Managed Cloud',
|
|
34
|
+
headerClass: HEADER_CLASSES[0],
|
|
35
|
+
links: [
|
|
36
|
+
{ label: 'NetFoundry Console', to: '#', logo: consoleLogo, description: 'Cloud-managed orchestration and global fabric control.' },
|
|
37
|
+
{ label: 'Frontdoor', to: '/docs/frontdoor', logo: `${img}/frontdoor-sm-logo.svg`, description: 'Secure application access gateway.' },
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
header: 'Open Source',
|
|
42
|
+
headerClass: HEADER_CLASSES[1],
|
|
43
|
+
links: [
|
|
44
|
+
{ label: 'OpenZiti', to: '/docs/openziti', logo: `${img}/openziti-sm-logo.svg`, description: 'Programmable zero-trust mesh infrastructure.' },
|
|
45
|
+
{ label: 'zrok', to: '/docs/zrok', logo: `${img}/zrok-1.0.0-rocket-purple.svg`, logoDark: `${img}/zrok-1.0.0-rocket-green.svg`, description: 'Secure peer-to-peer sharing built on OpenZiti.' },
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
header: 'Your own infrastructure',
|
|
50
|
+
headerClass: HEADER_CLASSES[2],
|
|
51
|
+
links: [
|
|
52
|
+
{ label: 'Self-Hosted', to: '/docs/selfhosted', logo: `${img}/onprem-sm-logo.svg`, description: 'Deploy the full stack in your own environment.' },
|
|
53
|
+
{ label: 'zLAN', to: '/docs/zlan', logo: `${img}/zlan/zlan-logo.svg`, description: 'Zero-trust access for OT networks.' },
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
export default function ProductPicker({label = 'Products', className}: Props) {
|
|
59
|
+
const {siteConfig} = useDocusaurusContext();
|
|
60
|
+
const themeConfig = useThemeConfig() as any;
|
|
61
|
+
const consoleLogo = themeConfig?.netfoundry?.consoleLogo ?? NF_LOGO_DEFAULT;
|
|
62
|
+
const img = `${siteConfig.url}${siteConfig.baseUrl}img`;
|
|
63
|
+
const columns: PickerColumn[] = (themeConfig?.netfoundry?.productPickerColumns ?? [])
|
|
64
|
+
.map((col: any, i: number) => ({...col, headerClass: HEADER_CLASSES[i] ?? ''}));
|
|
65
|
+
const resolvedColumns = columns.length ? columns : buildDefaultColumns(img, consoleLogo);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<NavbarPicker label={label} className={className}>
|
|
69
|
+
<div className="picker-content">
|
|
70
|
+
{resolvedColumns.map((col, i) => (
|
|
71
|
+
<div key={i} className="picker-column">
|
|
72
|
+
<span className={clsx('picker-header', col.headerClass)}>{col.header}</span>
|
|
73
|
+
{col.links.map((link, j) => (
|
|
74
|
+
<Link key={j} to={link.to} className="picker-link">
|
|
75
|
+
{link.logo && <img src={link.logo} className={clsx('picker-logo', link.logoDark && 'picker-logo--light')} alt="" />}
|
|
76
|
+
{link.logoDark && <img src={link.logoDark} className="picker-logo picker-logo--dark" alt="" />}
|
|
77
|
+
<div className="picker-text">
|
|
78
|
+
<strong>{link.label}</strong>
|
|
79
|
+
{link.description && <span>{link.description}</span>}
|
|
80
|
+
</div>
|
|
81
|
+
</Link>
|
|
82
|
+
))}
|
|
83
|
+
</div>
|
|
84
|
+
))}
|
|
85
|
+
</div>
|
|
86
|
+
</NavbarPicker>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Link from '@docusaurus/Link';
|
|
3
|
+
import {useThemeConfig} from '@docusaurus/theme-common';
|
|
4
|
+
import NavbarPicker from '../../NavbarPicker';
|
|
5
|
+
import {DiscourseIcon, YouTubeIcon} from '../../../../src/components/icons';
|
|
6
|
+
|
|
7
|
+
const NF_LOGO_DEFAULT = 'https://raw.githubusercontent.com/netfoundry/branding/refs/heads/main/images/svg/icon/netfoundry-icon-color.svg';
|
|
8
|
+
const OPENZITI_LOGO_DEFAULT = 'https://netfoundry.io/docs/img/openziti-sm-logo.svg';
|
|
9
|
+
|
|
10
|
+
type LogoLink = {
|
|
11
|
+
label: string;
|
|
12
|
+
description: string;
|
|
13
|
+
href: string;
|
|
14
|
+
logoSrc: string;
|
|
15
|
+
badge?: React.ReactElement;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type IconLink = {
|
|
19
|
+
label: string;
|
|
20
|
+
description: string;
|
|
21
|
+
href: string;
|
|
22
|
+
icon: React.ReactElement;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
type ResourceLink = LogoLink | IconLink;
|
|
26
|
+
|
|
27
|
+
function isLogoLink(link: ResourceLink): link is LogoLink {
|
|
28
|
+
return 'logoSrc' in link;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function ResourceLink({link}: {link: ResourceLink}) {
|
|
32
|
+
return (
|
|
33
|
+
<Link to={link.href} className="picker-link" target="_blank" rel="noopener noreferrer">
|
|
34
|
+
{isLogoLink(link) ? (
|
|
35
|
+
<span style={{position: 'relative', display: 'inline-flex', flexShrink: 0, marginRight: '0.8rem', width: 32, height: 32}}>
|
|
36
|
+
<img src={link.logoSrc} style={{width: 32, height: 32, objectFit: 'contain'}} alt="" />
|
|
37
|
+
{link.badge && (
|
|
38
|
+
<span style={{position: 'absolute', bottom: -2, right: -4, width: 14, height: 14, display: 'block'}}>
|
|
39
|
+
{link.badge}
|
|
40
|
+
</span>
|
|
41
|
+
)}
|
|
42
|
+
</span>
|
|
43
|
+
) : (
|
|
44
|
+
<span className="picker-logo">{link.icon}</span>
|
|
45
|
+
)}
|
|
46
|
+
<div className="picker-text">
|
|
47
|
+
<strong>{link.label}</strong>
|
|
48
|
+
<span>{link.description}</span>
|
|
49
|
+
</div>
|
|
50
|
+
</Link>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type Props = {
|
|
55
|
+
label?: string;
|
|
56
|
+
position?: 'left' | 'right';
|
|
57
|
+
className?: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default function ResourcesPicker({label = 'Resources', className}: Props) {
|
|
61
|
+
const themeConfig = useThemeConfig() as any;
|
|
62
|
+
const consoleLogo = themeConfig?.netfoundry?.consoleLogo ?? NF_LOGO_DEFAULT;
|
|
63
|
+
const openzitiLogo = themeConfig?.netfoundry?.openzitiLogo ?? OPENZITI_LOGO_DEFAULT;
|
|
64
|
+
|
|
65
|
+
const youtubeBadge = <YouTubeIcon width={14} height={14} />;
|
|
66
|
+
|
|
67
|
+
const learnLinks: ResourceLink[] = [
|
|
68
|
+
{ label: 'NetFoundry Blog', description: 'Latest news, updates, and insights from NetFoundry.', href: 'https://netfoundry.io/blog/', logoSrc: consoleLogo },
|
|
69
|
+
{ label: 'OpenZiti Tech Blog', description: 'Technical articles and community updates.', href: 'https://blog.openziti.io/', logoSrc: openzitiLogo },
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const communityLinks: ResourceLink[] = [
|
|
73
|
+
{ label: 'NetFoundry YouTube', description: 'Video tutorials, demos, and technical deep dives.', href: 'https://www.youtube.com/c/NetFoundry', logoSrc: consoleLogo, badge: youtubeBadge },
|
|
74
|
+
{ label: 'OpenZiti YouTube', description: 'OpenZiti community videos and project updates.', href: 'https://www.youtube.com/openziti', logoSrc: openzitiLogo, badge: youtubeBadge },
|
|
75
|
+
{ label: 'OpenZiti Discourse', description: 'Ask questions and connect with the community.', href: 'https://openziti.discourse.group/', icon: <DiscourseIcon width={32} height={32} /> },
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<NavbarPicker label={label} className={className} panelClassName="nf-picker-panel--narrow" autoPosition>
|
|
80
|
+
<div className="picker-column">
|
|
81
|
+
<span className="picker-header picker-header--nf-primary" style={{color: 'var(--ifm-color-primary)'}}>Learn & Engage</span>
|
|
82
|
+
{learnLinks.map((link, i) => <ResourceLink key={i} link={link} />)}
|
|
83
|
+
<span className="picker-header picker-header--nf-secondary" style={{marginTop: '0.75rem'}}>Community & Support</span>
|
|
84
|
+
{communityLinks.map((link, i) => <ResourceLink key={i} link={link} />)}
|
|
85
|
+
</div>
|
|
86
|
+
</NavbarPicker>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"WebFetch(domain:netfoundry.io)",
|
|
5
|
-
"WebSearch",
|
|
6
|
-
"WebFetch(domain:github.com)",
|
|
7
|
-
"WebFetch(domain:colineberhardt.github.io)",
|
|
8
|
-
"WebFetch(domain:cla-assistant.io)",
|
|
9
|
-
"WebFetch(domain:raw.githubusercontent.com)"
|
|
10
|
-
]
|
|
11
|
-
}
|
|
12
|
-
}
|