@conduction/docusaurus-preset 0.1.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.
Files changed (163) hide show
  1. package/MISSING_COMPONENTS.md +109 -0
  2. package/README.md +171 -0
  3. package/package.json +59 -0
  4. package/src/components/AgentTrace/AgentTrace.jsx +128 -0
  5. package/src/components/AgentTrace/AgentTrace.module.css +115 -0
  6. package/src/components/AppMock/AppMock.jsx +86 -0
  7. package/src/components/AppMock/AppMock.module.css +629 -0
  8. package/src/components/AppMock/variants/DeciDeskMock.jsx +71 -0
  9. package/src/components/AppMock/variants/DocuDeskMock.jsx +69 -0
  10. package/src/components/AppMock/variants/LarpingAppMock.jsx +59 -0
  11. package/src/components/AppMock/variants/MyDashBiMock.jsx +135 -0
  12. package/src/components/AppMock/variants/MyDashMock.jsx +96 -0
  13. package/src/components/AppMock/variants/MyDashTilesMock.jsx +103 -0
  14. package/src/components/AppMock/variants/MyDashWidgetsMock.jsx +123 -0
  15. package/src/components/AppMock/variants/NLDesignMock.jsx +70 -0
  16. package/src/components/AppMock/variants/OpenCatalogiMock.jsx +61 -0
  17. package/src/components/AppMock/variants/OpenConnectorMock.jsx +83 -0
  18. package/src/components/AppMock/variants/OpenRegisterMock.jsx +100 -0
  19. package/src/components/AppMock/variants/OpenWooMock.jsx +61 -0
  20. package/src/components/AppMock/variants/PipelinQMock.jsx +88 -0
  21. package/src/components/AppMock/variants/ProcestMock.jsx +87 -0
  22. package/src/components/AppMock/variants/SoftwareCatalogMock.jsx +71 -0
  23. package/src/components/AppMock/variants/ZaakAfhandelAppMock.jsx +71 -0
  24. package/src/components/AppsGrid/AppsGrid.jsx +84 -0
  25. package/src/components/AppsGrid/AppsGrid.module.css +46 -0
  26. package/src/components/AppsPreview/AppsPreview.jsx +85 -0
  27. package/src/components/AppsPreview/AppsPreview.module.css +128 -0
  28. package/src/components/Clients/Clients.jsx +205 -0
  29. package/src/components/Clients/Clients.module.css +166 -0
  30. package/src/components/ComposeBlock/ComposeBlock.jsx +70 -0
  31. package/src/components/ComposeBlock/ComposeBlock.module.css +74 -0
  32. package/src/components/ConductionBg/ConductionBg.jsx +150 -0
  33. package/src/components/ConductionBg/ConductionBg.module.css +41 -0
  34. package/src/components/ContentCard/ContentCard.jsx +126 -0
  35. package/src/components/ContentCard/ContentCard.module.css +84 -0
  36. package/src/components/ContentDetailHero/ContentDetailHero.jsx +136 -0
  37. package/src/components/ContentDetailHero/ContentDetailHero.module.css +96 -0
  38. package/src/components/ContentTypeFilter/ContentTypeFilter.jsx +103 -0
  39. package/src/components/ContentTypeFilter/ContentTypeFilter.module.css +60 -0
  40. package/src/components/ContentTypeFilter/contentTypes.js +58 -0
  41. package/src/components/CookieCli/CookieCli.jsx +223 -0
  42. package/src/components/CookieCli/CookieCli.module.css +166 -0
  43. package/src/components/CtaBanner/CtaBanner.jsx +61 -0
  44. package/src/components/CtaBanner/CtaBanner.module.css +65 -0
  45. package/src/components/DetailHero/DetailHero.jsx +143 -0
  46. package/src/components/DetailHero/DetailHero.module.css +154 -0
  47. package/src/components/Diagrams/Diagrams.jsx +148 -0
  48. package/src/components/EmployeeCard/EmployeeCard.jsx +127 -0
  49. package/src/components/EmployeeCard/EmployeeCard.module.css +144 -0
  50. package/src/components/ExternalAppShelf/ExternalAppShelf.jsx +61 -0
  51. package/src/components/ExternalAppShelf/ExternalAppShelf.module.css +90 -0
  52. package/src/components/FAQ/FAQ.jsx +42 -0
  53. package/src/components/FAQ/FAQ.module.css +74 -0
  54. package/src/components/FacetedFilters/FacetedFilters.jsx +125 -0
  55. package/src/components/FacetedFilters/FacetedFilters.module.css +133 -0
  56. package/src/components/FeatureGrid/FeatureGrid.jsx +94 -0
  57. package/src/components/FeatureGrid/FeatureGrid.module.css +114 -0
  58. package/src/components/FeatureList/FeatureList.jsx +54 -0
  59. package/src/components/FeatureList/FeatureList.module.css +52 -0
  60. package/src/components/FeaturedCard/FeaturedCard.jsx +101 -0
  61. package/src/components/FeaturedCard/FeaturedCard.module.css +98 -0
  62. package/src/components/GameModal/GameModal.jsx +197 -0
  63. package/src/components/GameModal/GameModal.module.css +184 -0
  64. package/src/components/Hero/Hero.jsx +101 -0
  65. package/src/components/Hero/Hero.module.css +95 -0
  66. package/src/components/HexBackground/HexBackground.jsx +56 -0
  67. package/src/components/HexBackground/HexBackground.module.css +73 -0
  68. package/src/components/HexNetwork/HexNetwork.jsx +141 -0
  69. package/src/components/HexNetwork/HexNetwork.module.css +187 -0
  70. package/src/components/HexRain/HexRain.jsx +81 -0
  71. package/src/components/HowSteps/HowSteps.jsx +57 -0
  72. package/src/components/HowSteps/HowSteps.module.css +52 -0
  73. package/src/components/ManagedCommonGround/ManagedCommonGround.jsx +78 -0
  74. package/src/components/ManagedCommonGround/ManagedCommonGround.module.css +16 -0
  75. package/src/components/NewsletterCta/NewsletterCta.jsx +83 -0
  76. package/src/components/NewsletterCta/NewsletterCta.module.css +103 -0
  77. package/src/components/PairCard/PairCard.jsx +58 -0
  78. package/src/components/PairCard/PairCard.module.css +54 -0
  79. package/src/components/PartnerCard/PartnerCard.jsx +130 -0
  80. package/src/components/PartnerCard/PartnerCard.module.css +198 -0
  81. package/src/components/PartnerDirectory/PartnerDirectory.jsx +122 -0
  82. package/src/components/PartnerDirectory/PartnerDirectory.module.css +25 -0
  83. package/src/components/PartnerSidecard/PartnerSidecard.jsx +116 -0
  84. package/src/components/PartnerSidecard/PartnerSidecard.module.css +185 -0
  85. package/src/components/Pipeline/Pipeline.jsx +198 -0
  86. package/src/components/Pipeline/Pipeline.module.css +206 -0
  87. package/src/components/PlatformDiagram/PlatformDiagram.jsx +110 -0
  88. package/src/components/PlatformOverview/PlatformOverview.jsx +68 -0
  89. package/src/components/PlatformOverview/PlatformOverview.module.css +71 -0
  90. package/src/components/ReferenceCard/ReferenceCard.jsx +44 -0
  91. package/src/components/ReferenceCard/ReferenceCard.module.css +57 -0
  92. package/src/components/RelatedPosts/RelatedPosts.jsx +58 -0
  93. package/src/components/RelatedPosts/RelatedPosts.module.css +51 -0
  94. package/src/components/RotatingCards/RotatingCards.jsx +98 -0
  95. package/src/components/RotatingCards/RotatingCards.module.css +153 -0
  96. package/src/components/Showcase/Showcase.jsx +129 -0
  97. package/src/components/Showcase/Showcase.module.css +168 -0
  98. package/src/components/SolutionCard/SolutionCard.jsx +83 -0
  99. package/src/components/SolutionCard/SolutionCard.module.css +99 -0
  100. package/src/components/StatsStrip/StatsStrip.jsx +38 -0
  101. package/src/components/StatsStrip/StatsStrip.module.css +53 -0
  102. package/src/components/WidgetShelf/WidgetShelf.jsx +67 -0
  103. package/src/components/WidgetShelf/WidgetShelf.module.css +73 -0
  104. package/src/components/index.js +96 -0
  105. package/src/components/primitives/AuthorByline.jsx +85 -0
  106. package/src/components/primitives/AuthorByline.module.css +57 -0
  107. package/src/components/primitives/BrandCitation.jsx +71 -0
  108. package/src/components/primitives/Button.jsx +46 -0
  109. package/src/components/primitives/Button.module.css +88 -0
  110. package/src/components/primitives/Card.jsx +42 -0
  111. package/src/components/primitives/Card.module.css +42 -0
  112. package/src/components/primitives/Eyebrow.jsx +37 -0
  113. package/src/components/primitives/Eyebrow.module.css +19 -0
  114. package/src/components/primitives/HexBullet.jsx +37 -0
  115. package/src/components/primitives/HexBullet.module.css +16 -0
  116. package/src/components/primitives/HexThumbnail.jsx +70 -0
  117. package/src/components/primitives/HexThumbnail.module.css +45 -0
  118. package/src/components/primitives/Pill.jsx +42 -0
  119. package/src/components/primitives/Pill.module.css +30 -0
  120. package/src/components/primitives/Section.jsx +51 -0
  121. package/src/components/primitives/Section.module.css +31 -0
  122. package/src/components/primitives/SectionHead.jsx +36 -0
  123. package/src/components/primitives/SectionHead.module.css +43 -0
  124. package/src/components/primitives/index.js +22 -0
  125. package/src/css/brand.css +158 -0
  126. package/src/css/tokens.css +12 -0
  127. package/src/data/app-downloads.js +42 -0
  128. package/src/diagrams/README.md +74 -0
  129. package/src/diagrams/cn-domain-tree.js +105 -0
  130. package/src/diagrams/cn-hex-prism.js +163 -0
  131. package/src/diagrams/cn-hex.js +181 -0
  132. package/src/diagrams/cn-honeycomb-bg.js +135 -0
  133. package/src/diagrams/cn-pipeline.js +150 -0
  134. package/src/diagrams/cn-platform.js +156 -0
  135. package/src/diagrams/cn-side-box.js +104 -0
  136. package/src/diagrams/index.js +28 -0
  137. package/src/index.js +183 -0
  138. package/src/theme/Footer/index.jsx +516 -0
  139. package/src/theme/MDXPage/index.jsx +134 -0
  140. package/src/theme/Navbar/index.jsx +120 -0
  141. package/src/theme/Navbar/styles.module.css +114 -0
  142. package/src/theme/brand.jsx +63 -0
  143. package/src/theme.js +45 -0
  144. package/src/utils/lazyScript.js +37 -0
  145. package/static/img/favicon.svg +14 -0
  146. package/static/img/honeycomb-scatter.svg +23 -0
  147. package/static/img/honeycomb-watermark.svg +108 -0
  148. package/static/img/logo-dark.svg +11 -0
  149. package/static/img/logo.svg +14 -0
  150. package/static/img/nextcloud-logo.svg +5 -0
  151. package/static/lib/canal-footer.css +418 -0
  152. package/static/lib/canal-footer.js +499 -0
  153. package/static/lib/clients-flow.js +317 -0
  154. package/static/lib/conduction-bg.css +50 -0
  155. package/static/lib/conduction-bg.js +122 -0
  156. package/static/lib/hex-rain.css +128 -0
  157. package/static/lib/hex-rain.js +284 -0
  158. package/static/lib/kade-cyclist.css +264 -0
  159. package/static/lib/kade-cyclist.js +420 -0
  160. package/static/lib/logo-memory.css +219 -0
  161. package/static/lib/logo-memory.js +540 -0
  162. package/static/lib/platform-diagram.css +458 -0
  163. package/static/lib/platform-diagram.js +414 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Brand MDXPage swizzle.
3
+ *
4
+ * Docusaurus's default MDXPage wraps every MDX page in
5
+ * `<main class="container">.row > .col col--8`, which constrains content
6
+ * to 67% width with a margin column reserved for the TOC. That works
7
+ * for documentation pages but kills the design of marketing pages: the
8
+ * cobalt-50 stats band, the canal-scene footer, and every cobalt CTA
9
+ * panel render with visible white margins instead of bleeding to the
10
+ * edges.
11
+ *
12
+ * Brand rule: pages with `hide_table_of_contents: true` (every page in
13
+ * sites/www/src/pages/) render full-width. Section components own
14
+ * their own `max-width: 1280px; margin: 0 auto` rules, so the marketing
15
+ * surfaces look right. Pages that DO show a TOC keep the standard
16
+ * Docusaurus container behaviour so the docs side stays consistent.
17
+ *
18
+ * Mirrors the source upstream MDXPage signature so the rest of the
19
+ * Docusaurus renderer (PageMetadata, HtmlClassNameProvider, etc.) is
20
+ * untouched.
21
+ */
22
+
23
+ import React from 'react';
24
+ import clsx from 'clsx';
25
+ import {
26
+ PageMetadata,
27
+ HtmlClassNameProvider,
28
+ ThemeClassNames,
29
+ } from '@docusaurus/theme-common';
30
+ import Layout from '@theme/Layout';
31
+ import MDXContent from '@theme/MDXContent';
32
+ import TOC from '@theme/TOC';
33
+ import ContentVisibility from '@theme/ContentVisibility';
34
+ import EditMetaRow from '@theme/EditMetaRow';
35
+
36
+ export default function MDXPage(props) {
37
+ const {content: MDXPageContent} = props;
38
+ const {metadata, assets} = MDXPageContent;
39
+ const {
40
+ title,
41
+ editUrl,
42
+ description,
43
+ frontMatter,
44
+ lastUpdatedBy,
45
+ lastUpdatedAt,
46
+ } = metadata;
47
+ const {
48
+ keywords,
49
+ wrapperClassName,
50
+ hide_table_of_contents: hideTableOfContents,
51
+ } = frontMatter;
52
+ const image = assets.image ?? frontMatter.image;
53
+ const canDisplayEditMetaRow = !!(editUrl || lastUpdatedAt || lastUpdatedBy);
54
+
55
+ /* Marketing pages that opt out of the TOC also opt out of the col-8
56
+ container; the section components inside the page handle their own
57
+ widths and bleed to the edges where the design calls for it. */
58
+ const isMarketing = !!hideTableOfContents;
59
+
60
+ /* Marketing pages get article-margin: 0 so the first section of the
61
+ page (Hero, Section, etc.) sits flush against the navbar. The
62
+ default Infima styling on <article> would otherwise leave a small
63
+ top margin between the navbar's border and the page's first row,
64
+ which the user-flagged screenshot showed on the connext landing.
65
+ Docs pages keep the default margin so the heading rhythm reads
66
+ correctly. */
67
+ const articleStyle = isMarketing ? {margin: 0, padding: 0} : undefined;
68
+
69
+ const inner = (
70
+ <>
71
+ <ContentVisibility metadata={metadata} />
72
+ <article style={articleStyle}>
73
+ <MDXContent>
74
+ <MDXPageContent />
75
+ </MDXContent>
76
+ </article>
77
+ {canDisplayEditMetaRow && (
78
+ <EditMetaRow
79
+ className={clsx(
80
+ 'margin-top--sm',
81
+ ThemeClassNames.pages.pageFooterEditMetaRow,
82
+ )}
83
+ editUrl={editUrl}
84
+ lastUpdatedAt={lastUpdatedAt}
85
+ lastUpdatedBy={lastUpdatedBy}
86
+ />
87
+ )}
88
+ </>
89
+ );
90
+
91
+ return (
92
+ <HtmlClassNameProvider
93
+ className={clsx(
94
+ wrapperClassName ?? ThemeClassNames.wrapper.mdxPages,
95
+ ThemeClassNames.page.mdxPage,
96
+ )}>
97
+ <Layout>
98
+ <PageMetadata
99
+ title={title}
100
+ description={description}
101
+ keywords={keywords}
102
+ image={image}
103
+ />
104
+ {isMarketing ? (
105
+ /* Marketing surface: no container, no col-8. The page's
106
+ section components own their own widths. The
107
+ `marketing-page` class lets brand.css zero-out any stray
108
+ top margin/padding so the first section sits flush
109
+ against the navbar (no gap between navbar and hex-rain
110
+ hero). */
111
+ <main className="marketing-page">{inner}</main>
112
+ ) : (
113
+ /* Docs / TOC surface: standard Docusaurus container. */
114
+ <main className="container container--fluid margin-vert--lg">
115
+ <div className="row">
116
+ <div className={clsx('col', MDXPageContent.toc.length > 0 && 'col--8')}>
117
+ {inner}
118
+ </div>
119
+ {MDXPageContent.toc.length > 0 && (
120
+ <div className="col col--2">
121
+ <TOC
122
+ toc={MDXPageContent.toc}
123
+ minHeadingLevel={frontMatter.toc_min_heading_level}
124
+ maxHeadingLevel={frontMatter.toc_max_heading_level}
125
+ />
126
+ </div>
127
+ )}
128
+ </div>
129
+ </main>
130
+ )}
131
+ </Layout>
132
+ </HtmlClassNameProvider>
133
+ );
134
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Brand Navbar swizzle.
3
+ *
4
+ * Replaces Docusaurus's default Infima navbar with the Conduction
5
+ * top-navbar pattern: brand wordmark + nav links + Partners + Install.
6
+ * Navigation items come from themeConfig.navbar.items (configured by
7
+ * the consuming site); the chrome (typography, spacing, brand citation)
8
+ * stays locked in this component.
9
+ *
10
+ * Brand wordmark switches based on pathname so a single Conduction hub
11
+ * can host vanity sub-brand entry points:
12
+ *
13
+ * /connext, /nl/connext → "Con<Next>" with next-blue accent
14
+ * /commonground, /nl/commonground → "Common <Ground>" with cg-yellow accent
15
+ * anything else → navbar.title (e.g. "Conduction")
16
+ *
17
+ * The home link follows the brand: clicking the wordmark while on a
18
+ * sub-brand section keeps you in that section. Outside a sub-brand
19
+ * section it goes to the site root.
20
+ *
21
+ * Mirrors preview/components/top-navbar.html in the design-system kit.
22
+ */
23
+
24
+ import React from 'react';
25
+ import Link from '@docusaurus/Link';
26
+ import {useLocation} from '@docusaurus/router';
27
+ import {useThemeConfig} from '@docusaurus/theme-common';
28
+ import LocaleDropdownNavbarItem from '@theme/NavbarItem/LocaleDropdownNavbarItem';
29
+ import {brandFor} from '../brand.jsx';
30
+ import styles from './styles.module.css';
31
+
32
+ /**
33
+ * Render a single navbar item. The brand top-navbar supports a small
34
+ * subset of Docusaurus item types (link, locale dropdown, optional
35
+ * primary CTA via items[].cta = true). Everything else falls back to
36
+ * a plain link for forward-compatibility.
37
+ */
38
+ function NavItem({item, location}) {
39
+ if (item.type === 'localeDropdown') {
40
+ return (
41
+ <div className={styles.localeWrapper}>
42
+ <LocaleDropdownNavbarItem mobile={false} {...item} />
43
+ </div>
44
+ );
45
+ }
46
+
47
+ /* External link, no React-router prefetch */
48
+ if (item.href && !item.to) {
49
+ const isCta = item.cta === true;
50
+ return (
51
+ <a
52
+ href={item.href}
53
+ className={isCta ? styles.cta : styles.ghost}
54
+ target={item.href.startsWith('http') ? '_blank' : undefined}
55
+ rel={item.href.startsWith('http') ? 'noopener noreferrer' : undefined}
56
+ >
57
+ {item.label}{isCta && ' →'}
58
+ </a>
59
+ );
60
+ }
61
+
62
+ /* Internal route */
63
+ if (item.to) {
64
+ const isCta = item.cta === true;
65
+ const isActive = location?.pathname === item.to ||
66
+ location?.pathname?.startsWith(item.to + '/');
67
+ return (
68
+ <Link
69
+ to={item.to}
70
+ className={
71
+ isCta
72
+ ? styles.cta
73
+ : `${styles.link} ${isActive ? styles.linkActive : ''}`
74
+ }
75
+ >
76
+ {item.label}{isCta && ' →'}
77
+ </Link>
78
+ );
79
+ }
80
+
81
+ return null;
82
+ }
83
+
84
+ export default function Navbar() {
85
+ const {navbar} = useThemeConfig();
86
+ const location = useLocation();
87
+ const items = navbar.items || [];
88
+ const brand = brandFor(location.pathname, navbar.title);
89
+ const wordmark = brand ? brand.wordmark : navbar.title;
90
+ /* Path-match: keep the visitor in the sub-brand section on logo click.
91
+ Title-match (the site's primary brand IS a sub-brand): logo goes to
92
+ site root since the section IS the site. */
93
+ const homeHref = brand?.source === 'path' ? brand.home : '/';
94
+
95
+ /* Split into "left links" (regular nav) and "right CTAs" (locale,
96
+ external links, install button). The brand pattern groups them
97
+ this way; consumers control order via item.position. */
98
+ const leftItems = items.filter(i => i.position !== 'right' && i.type !== 'localeDropdown');
99
+ const rightItems = items.filter(i => i.position === 'right' || i.type === 'localeDropdown');
100
+
101
+ return (
102
+ <nav className={styles.nav} role="navigation" aria-label="Main">
103
+ <div className={styles.left}>
104
+ <Link to={homeHref} className={styles.wordmark}>
105
+ {wordmark}
106
+ </Link>
107
+ <div className={styles.links}>
108
+ {leftItems.map((item, i) => (
109
+ <NavItem key={i} item={item} location={location} />
110
+ ))}
111
+ </div>
112
+ </div>
113
+ <div className={styles.ctas}>
114
+ {rightItems.map((item, i) => (
115
+ <NavItem key={i} item={item} location={location} />
116
+ ))}
117
+ </div>
118
+ </nav>
119
+ );
120
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Navbar swizzle styles. Mirrors preview/components/top-navbar.html in
3
+ * the design-system kit. CSS Modules so class names don't collide with
4
+ * Docusaurus's Infima rules.
5
+ */
6
+
7
+ .nav {
8
+ display: flex;
9
+ align-items: center;
10
+ justify-content: space-between;
11
+ padding: 22px 56px;
12
+ border-bottom: 1px solid var(--c-cobalt-100);
13
+ background: white;
14
+ position: sticky;
15
+ top: 0;
16
+ z-index: 100;
17
+ font-family: var(--conduction-typography-font-family-body);
18
+ }
19
+
20
+ .left {
21
+ display: flex;
22
+ align-items: center;
23
+ gap: 44px;
24
+ }
25
+
26
+ .wordmark {
27
+ font-size: 22px;
28
+ font-weight: 700;
29
+ letter-spacing: -0.02em;
30
+ color: var(--c-blue-cobalt);
31
+ text-decoration: none;
32
+ }
33
+ .wordmark:hover { color: var(--c-blue-cobalt); text-decoration: none; }
34
+
35
+ .links {
36
+ display: flex;
37
+ gap: 28px;
38
+ }
39
+
40
+ .link {
41
+ color: var(--c-cobalt-700);
42
+ text-decoration: none;
43
+ font-size: 14px;
44
+ font-weight: 500;
45
+ transition: color 160ms ease;
46
+ }
47
+ .link:hover {
48
+ color: var(--c-orange-knvb);
49
+ text-decoration: none;
50
+ }
51
+ .linkActive {
52
+ color: var(--c-orange-knvb);
53
+ font-weight: 600;
54
+ }
55
+
56
+ .ctas {
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 12px;
60
+ }
61
+
62
+ .ghost {
63
+ color: var(--c-cobalt-700);
64
+ text-decoration: none;
65
+ font-size: 14px;
66
+ font-weight: 500;
67
+ }
68
+ .ghost:hover {
69
+ color: var(--c-orange-knvb);
70
+ text-decoration: none;
71
+ }
72
+
73
+ .cta {
74
+ background: var(--c-blue-cobalt);
75
+ color: white;
76
+ padding: 9px 16px;
77
+ border-radius: var(--radius-md);
78
+ font-size: 14px;
79
+ font-weight: 500;
80
+ text-decoration: none;
81
+ transition: background 160ms ease;
82
+ }
83
+ .cta:hover {
84
+ background: var(--c-cobalt-700);
85
+ color: white;
86
+ text-decoration: none;
87
+ }
88
+
89
+ /* Locale dropdown integration. Override Infima's defaults so it sits
90
+ inline with the other right-side items. */
91
+ .localeWrapper :global(.dropdown) {
92
+ font-size: 14px;
93
+ }
94
+ .localeWrapper :global(.navbar__link) {
95
+ color: var(--c-cobalt-700);
96
+ font-weight: 500;
97
+ padding: 0 8px;
98
+ }
99
+ .localeWrapper :global(.navbar__link:hover) {
100
+ color: var(--c-orange-knvb);
101
+ }
102
+
103
+ /* Responsive collapse, simplified for v1.
104
+ TODO: hamburger menu like the design-system mock. */
105
+ @media (max-width: 900px) {
106
+ .nav {
107
+ padding: 16px 24px;
108
+ flex-wrap: wrap;
109
+ gap: 16px;
110
+ }
111
+ .left { gap: 16px; }
112
+ .links { gap: 16px; }
113
+ .ctas { gap: 8px; }
114
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Sub-brand detection for the Conduction hub.
3
+ *
4
+ * The hub at conduction.nl hosts ConNext and Common Ground vanity
5
+ * sections at /connext and /commonground (with locale-prefixed twins
6
+ * at /nl/connext and /nl/commonground). When a visitor is browsing
7
+ * inside a sub-brand section, the navbar wordmark and the footer
8
+ * brand block both switch to that sub-brand's mark. Outside any
9
+ * sub-brand section the default (Conduction, or whatever
10
+ * navbar.title is set to) wins.
11
+ *
12
+ * Both the Navbar and Footer swizzles import from here so the
13
+ * regex, wordmark JSX, and label stay in one place.
14
+ */
15
+
16
+ import React from 'react';
17
+
18
+ export const SUB_BRANDS = [
19
+ {
20
+ name: 'connext',
21
+ match: /^(?:\/nl)?\/connext(?:\/|$)/,
22
+ home: '/connext',
23
+ label: 'ConNext',
24
+ wordmark: (
25
+ <>
26
+ Con<span className="next-blue">Next</span>
27
+ </>
28
+ ),
29
+ },
30
+ {
31
+ name: 'commonground',
32
+ match: /^(?:\/nl)?\/commonground(?:\/|$)/,
33
+ home: '/commonground',
34
+ label: 'Common Ground+',
35
+ wordmark: (
36
+ <>
37
+ <span className="cg-plus-common">Common</span>{' '}
38
+ <span className="cg-yellow">Ground</span>
39
+ <span className="cg-plus-plus">+</span>
40
+ </>
41
+ ),
42
+ },
43
+ ];
44
+
45
+ /**
46
+ * Pick the sub-brand active for a pathname. Falls back to title-based
47
+ * detection so a site whose primary brand IS a sub-brand (e.g. its
48
+ * navbar.title is set to 'ConNext') still gets the styled wordmark.
49
+ *
50
+ * Returns the matched SUB_BRANDS entry, or null if no match (default
51
+ * means the consumer should fall back to its own default text).
52
+ */
53
+ export function brandFor(pathname, title) {
54
+ for (const b of SUB_BRANDS) {
55
+ if (b.match.test(pathname)) return {...b, source: 'path'};
56
+ }
57
+ if (title) {
58
+ for (const b of SUB_BRANDS) {
59
+ if (b.label === title) return {...b, source: 'title'};
60
+ }
61
+ }
62
+ return null;
63
+ }
package/src/theme.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @conduction/docusaurus-preset, theme plugin entry.
3
+ *
4
+ * Registers the brand theme with Docusaurus so swizzled components
5
+ * (Navbar, Footer, future Doc / DocItem / etc.) replace the Infima
6
+ * defaults automatically. Sites pick this up by including it in
7
+ * themes: [...] (createConfig() does this for you).
8
+ *
9
+ * The brand CSS (token mapping + brand atoms) is also registered here
10
+ * via getClientModules() so it loads on every page without the site
11
+ * having to wire it into customCss.
12
+ */
13
+
14
+ const path = require('path');
15
+
16
+ module.exports = function conductionTheme(context, options) {
17
+ return {
18
+ name: '@conduction/docusaurus-theme',
19
+
20
+ /**
21
+ * Tells Docusaurus where to find swizzleable theme components.
22
+ * Anything under ./theme/<ComponentName>/ overrides the matching
23
+ * Docusaurus default.
24
+ */
25
+ getThemePath() {
26
+ return path.resolve(__dirname, './theme');
27
+ },
28
+
29
+ /**
30
+ * Same path, exposed for the `docusaurus swizzle` CLI so consumers
31
+ * can list / eject our overrides if they need to customise further.
32
+ */
33
+ getTypeScriptThemePath() {
34
+ return path.resolve(__dirname, './theme');
35
+ },
36
+
37
+ /**
38
+ * Brand CSS auto-loaded on every page. Sites can still append more
39
+ * via customCss[]; the preset's createConfig() wires that through.
40
+ */
41
+ getClientModules() {
42
+ return [path.resolve(__dirname, './css/brand.css')];
43
+ },
44
+ };
45
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * useLazyScript: load a runtime script after React hydration.
3
+ *
4
+ * The pattern used in this preset's heavier components (canal-footer,
5
+ * hex-rain, platform-diagram) was to inject the runtime via
6
+ * `<Head><script defer /></Head>`. Defer scripts run between HTML
7
+ * parse and DOMContentLoaded, which is *before* React hydration in
8
+ * production builds. The scripts mutate the DOM (filling .skyline,
9
+ * upgrading custom elements, etc.), and the mutated DOM no longer
10
+ * matches what React tries to hydrate, producing minified errors
11
+ * #418 (hydration mismatch) + #423 (recovered by client re-render).
12
+ *
13
+ * Loading via this hook injects the <script> tag into <body> from a
14
+ * useEffect, which fires *after* hydration completes. The script's
15
+ * DOM mutations are then post-hydration and React doesn't re-validate.
16
+ *
17
+ * The injected tag has data-lazy-script="<key>" so SPA route changes
18
+ * don't double-load the same runtime, and so consumers can listen
19
+ * for `load` events on it (e.g. hex-rain calls window.HexRain.hydrate
20
+ * once the runtime registers itself).
21
+ */
22
+
23
+ import {useEffect} from 'react';
24
+ import useIsBrowser from '@docusaurus/useIsBrowser';
25
+
26
+ export function useLazyScript(src, key) {
27
+ const isBrowser = useIsBrowser();
28
+ useEffect(() => {
29
+ if (!isBrowser) return;
30
+ if (document.querySelector(`script[data-lazy-script="${key}"]`)) return;
31
+ const script = document.createElement('script');
32
+ script.src = src;
33
+ script.async = true;
34
+ script.dataset.lazyScript = key;
35
+ document.body.appendChild(script);
36
+ }, [isBrowser, src, key]);
37
+ }
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="-86.6 -100 173.2 200" role="img" aria-label="Conduction avatar">
3
+ <title>Conduction avatar, drawn as three pointy-top polygons</title>
4
+ <!-- viewBox is the bounding box of the outer hex (R=100), no
5
+ internal padding. Three polygons in the same drawing
6
+ vocabulary as the watermark hexes:
7
+ 1. Outer hex cobalt, the frame
8
+ 2. Inner hex white, the empty interior (so the
9
+ logo reads correctly on any ground)
10
+ 3. C-shape cobalt, sits inside the inner hex -->
11
+ <polygon fill="#21468B" points="0,-100 86.6,-50 86.6,50 0,100 -86.6,50 -86.6,-50"/>
12
+ <polygon fill="#FFFFFF" points="0,-74.5 64.5,-37.3 64.5,37.3 0,74.5 -64.5,37.3 -64.5,-37.3"/>
13
+ <polygon fill="#21468B" points="-0.2,-25.2 20.1,-13.5 43.7,-27.1 -0.2,-52.4 -45.6,-26.2 -45.6,26.2 -0.2,52.4 43.7,27.1 20.1,13.5 -0.2,25.2 -22,12.6 -22,-12.6"/>
14
+ </svg>
@@ -0,0 +1,23 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 450" width="800" height="450" preserveAspectRatio="xMidYMid slice" role="img" aria-label="Hex scatter overlay">
2
+ <title>Hex scatter, solid-fill cobalt tones</title>
3
+ <!-- Twelve pointy-top hexes, all solid fills from the cobalt ramp.
4
+ Mix of cobalt-700 and cobalt-800 reads as "darker" against
5
+ cobalt-900 grounds and "darker still" against blue-cobalt
6
+ grounds, giving a visible but quiet hex texture either way.
7
+ No transparency, no gradients. One orange accent per scene
8
+ is added by the foreground, never here. -->
9
+ <g>
10
+ <polygon points="120,40 165,66 165,118 120,144 75,118 75,66" fill="#152D5C"/>
11
+ <polygon points="280,80 325,106 325,158 280,184 235,158 235,106" fill="#102246"/>
12
+ <polygon points="450,30 510,64 510,132 450,166 390,132 390,64" fill="#152D5C"/>
13
+ <polygon points="630,90 675,116 675,168 630,194 585,168 585,116" fill="#102246"/>
14
+ <polygon points="760,40 800,63 800,109 760,132 720,109 720,63" fill="#152D5C"/>
15
+ <polygon points="60,200 90,217 90,253 60,270 30,253 30,217" fill="#102246"/>
16
+ <polygon points="200,260 245,286 245,338 200,364 155,338 155,286" fill="#152D5C"/>
17
+ <polygon points="370,310 410,333 410,379 370,402 330,379 330,333" fill="#102246"/>
18
+ <polygon points="540,290 590,318 590,374 540,402 490,374 490,318" fill="#152D5C"/>
19
+ <polygon points="700,260 740,283 740,329 700,352 660,329 660,283" fill="#102246"/>
20
+ <polygon points="100,360 140,383 140,429 100,452 60,429 60,383" fill="#152D5C"/>
21
+ <polygon points="380,150 410,167 410,203 380,220 350,203 350,167" fill="#102246"/>
22
+ </g>
23
+ </svg>
@@ -0,0 +1,108 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 297" width="210mm" height="297mm" preserveAspectRatio="xMidYMid slice" role="img" aria-label="Honeycomb watermark for A4 stationery">
2
+ <title>Honeycomb watermark, point-up hexes with scattered orange accents</title>
3
+ <!-- A4 watermark. Real honeycomb tiling with R=20mm.
4
+ Bulk hexes are stroked in cobalt-100 (solid colour), the
5
+ scattered accents are filled solid in KNVB orange. No fill-
6
+ opacity, no rgba, no gradients. All hexes point up. -->
7
+ <defs>
8
+ <!-- R=14 drawn hexes on a grid spaced for R=20: 6mm of breathing
9
+ room around each hex, never touching, still reading as a
10
+ honeycomb arrangement. -->
11
+ <polygon id="hx" points="0,-14 12.124,-7 12.124,7 0,14 -12.124,7 -12.124,-7"/>
12
+ </defs>
13
+
14
+ <!-- Cobalt-outlined hexes — the comb -->
15
+ <g fill="none" stroke="#DCE3F0" stroke-width="0.4">
16
+ <!-- Row 0 (type A, y=20) -->
17
+ <use href="#hx" x="17.32" y="20"/>
18
+ <use href="#hx" x="51.96" y="20"/>
19
+ <use href="#hx" x="86.6" y="20"/>
20
+ <use href="#hx" x="121.24" y="20"/>
21
+ <use href="#hx" x="155.88" y="20"/>
22
+ <use href="#hx" x="190.52" y="20"/>
23
+
24
+ <!-- Row 1 (type B, y=50) -->
25
+ <use href="#hx" x="0" y="50"/>
26
+ <use href="#hx" x="34.64" y="50"/>
27
+ <use href="#hx" x="103.92" y="50"/>
28
+ <use href="#hx" x="138.56" y="50"/>
29
+ <use href="#hx" x="173.2" y="50"/>
30
+ <use href="#hx" x="207.84" y="50"/>
31
+
32
+ <!-- Row 2 (type A, y=80) -->
33
+ <use href="#hx" x="17.32" y="80"/>
34
+ <use href="#hx" x="51.96" y="80"/>
35
+ <use href="#hx" x="86.6" y="80"/>
36
+ <use href="#hx" x="121.24" y="80"/>
37
+ <use href="#hx" x="155.88" y="80"/>
38
+ <use href="#hx" x="190.52" y="80"/>
39
+
40
+ <!-- Row 3 (type B, y=110) -->
41
+ <use href="#hx" x="0" y="110"/>
42
+ <use href="#hx" x="34.64" y="110"/>
43
+ <use href="#hx" x="69.28" y="110"/>
44
+ <use href="#hx" x="103.92" y="110"/>
45
+ <use href="#hx" x="138.56" y="110"/>
46
+ <use href="#hx" x="207.84" y="110"/>
47
+
48
+ <!-- Row 4 (type A, y=140) -->
49
+ <use href="#hx" x="17.32" y="140"/>
50
+ <use href="#hx" x="51.96" y="140"/>
51
+ <use href="#hx" x="86.6" y="140"/>
52
+ <use href="#hx" x="121.24" y="140"/>
53
+ <use href="#hx" x="155.88" y="140"/>
54
+ <use href="#hx" x="190.52" y="140"/>
55
+
56
+ <!-- Row 5 (type B, y=170) -->
57
+ <use href="#hx" x="0" y="170"/>
58
+ <use href="#hx" x="69.28" y="170"/>
59
+ <use href="#hx" x="103.92" y="170"/>
60
+ <use href="#hx" x="138.56" y="170"/>
61
+ <use href="#hx" x="173.2" y="170"/>
62
+ <use href="#hx" x="207.84" y="170"/>
63
+
64
+ <!-- Row 6 (type A, y=200) -->
65
+ <use href="#hx" x="17.32" y="200"/>
66
+ <use href="#hx" x="51.96" y="200"/>
67
+ <use href="#hx" x="86.6" y="200"/>
68
+ <use href="#hx" x="121.24" y="200"/>
69
+ <use href="#hx" x="155.88" y="200"/>
70
+ <use href="#hx" x="190.52" y="200"/>
71
+
72
+ <!-- Row 7 (type B, y=230) -->
73
+ <use href="#hx" x="0" y="230"/>
74
+ <use href="#hx" x="34.64" y="230"/>
75
+ <use href="#hx" x="69.28" y="230"/>
76
+ <use href="#hx" x="103.92" y="230"/>
77
+ <use href="#hx" x="173.2" y="230"/>
78
+ <use href="#hx" x="207.84" y="230"/>
79
+
80
+ <!-- Row 8 (type A, y=260) -->
81
+ <use href="#hx" x="17.32" y="260"/>
82
+ <use href="#hx" x="51.96" y="260"/>
83
+ <use href="#hx" x="86.6" y="260"/>
84
+ <use href="#hx" x="121.24" y="260"/>
85
+ <use href="#hx" x="155.88" y="260"/>
86
+ <use href="#hx" x="190.52" y="260"/>
87
+
88
+ <!-- Row 9 (type B, y=290) -->
89
+ <use href="#hx" x="0" y="290"/>
90
+ <use href="#hx" x="34.64" y="290"/>
91
+ <use href="#hx" x="69.28" y="290"/>
92
+ <use href="#hx" x="138.56" y="290"/>
93
+ <use href="#hx" x="173.2" y="290"/>
94
+ <use href="#hx" x="207.84" y="290"/>
95
+ </g>
96
+
97
+ <!-- Scattered cobalt accents — five, outline only.
98
+ Same stroke-width as the cobalt-100 bulk hexes; the brand
99
+ cobalt is naturally darker than cobalt-100 so the accents
100
+ read as a quieter highlight without overpowering body text. -->
101
+ <g fill="none" stroke="#21468B" stroke-width="0.4">
102
+ <use href="#hx" x="69.28" y="50"/>
103
+ <use href="#hx" x="173.2" y="110"/>
104
+ <use href="#hx" x="34.64" y="170"/>
105
+ <use href="#hx" x="138.56" y="230"/>
106
+ <use href="#hx" x="103.92" y="290"/>
107
+ </g>
108
+ </svg>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="-86.6 -100 173.2 200" role="img" aria-label="Conduction avatar, white">
3
+ <title>Conduction avatar, white, drawn as polygons (no background)</title>
4
+ <!-- For dark grounds. The cobalt-on-light cousin draws an inner
5
+ white polygon to force the interior; here the ground is
6
+ already dark so we let it show through, and the frame
7
+ collapses to a single hex with a hole, drawn via even-odd
8
+ fill of one path. Plus the C-shape on top in white. -->
9
+ <path fill="#FFFFFF" fill-rule="evenodd" d="M0,-100 L86.6,-50 L86.6,50 L0,100 L-86.6,50 L-86.6,-50 Z M0,-74.5 L64.5,-37.3 L64.5,37.3 L0,74.5 L-64.5,37.3 L-64.5,-37.3 Z"/>
10
+ <polygon fill="#FFFFFF" points="-0.2,-25.2 20.1,-13.5 43.7,-27.1 -0.2,-52.4 -45.6,-26.2 -45.6,26.2 -0.2,52.4 43.7,27.1 20.1,13.5 -0.2,25.2 -22,12.6 -22,-12.6"/>
11
+ </svg>