@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.
- package/MISSING_COMPONENTS.md +109 -0
- package/README.md +171 -0
- package/package.json +59 -0
- package/src/components/AgentTrace/AgentTrace.jsx +128 -0
- package/src/components/AgentTrace/AgentTrace.module.css +115 -0
- package/src/components/AppMock/AppMock.jsx +86 -0
- package/src/components/AppMock/AppMock.module.css +629 -0
- package/src/components/AppMock/variants/DeciDeskMock.jsx +71 -0
- package/src/components/AppMock/variants/DocuDeskMock.jsx +69 -0
- package/src/components/AppMock/variants/LarpingAppMock.jsx +59 -0
- package/src/components/AppMock/variants/MyDashBiMock.jsx +135 -0
- package/src/components/AppMock/variants/MyDashMock.jsx +96 -0
- package/src/components/AppMock/variants/MyDashTilesMock.jsx +103 -0
- package/src/components/AppMock/variants/MyDashWidgetsMock.jsx +123 -0
- package/src/components/AppMock/variants/NLDesignMock.jsx +70 -0
- package/src/components/AppMock/variants/OpenCatalogiMock.jsx +61 -0
- package/src/components/AppMock/variants/OpenConnectorMock.jsx +83 -0
- package/src/components/AppMock/variants/OpenRegisterMock.jsx +100 -0
- package/src/components/AppMock/variants/OpenWooMock.jsx +61 -0
- package/src/components/AppMock/variants/PipelinQMock.jsx +88 -0
- package/src/components/AppMock/variants/ProcestMock.jsx +87 -0
- package/src/components/AppMock/variants/SoftwareCatalogMock.jsx +71 -0
- package/src/components/AppMock/variants/ZaakAfhandelAppMock.jsx +71 -0
- package/src/components/AppsGrid/AppsGrid.jsx +84 -0
- package/src/components/AppsGrid/AppsGrid.module.css +46 -0
- package/src/components/AppsPreview/AppsPreview.jsx +85 -0
- package/src/components/AppsPreview/AppsPreview.module.css +128 -0
- package/src/components/Clients/Clients.jsx +205 -0
- package/src/components/Clients/Clients.module.css +166 -0
- package/src/components/ComposeBlock/ComposeBlock.jsx +70 -0
- package/src/components/ComposeBlock/ComposeBlock.module.css +74 -0
- package/src/components/ConductionBg/ConductionBg.jsx +150 -0
- package/src/components/ConductionBg/ConductionBg.module.css +41 -0
- package/src/components/ContentCard/ContentCard.jsx +126 -0
- package/src/components/ContentCard/ContentCard.module.css +84 -0
- package/src/components/ContentDetailHero/ContentDetailHero.jsx +136 -0
- package/src/components/ContentDetailHero/ContentDetailHero.module.css +96 -0
- package/src/components/ContentTypeFilter/ContentTypeFilter.jsx +103 -0
- package/src/components/ContentTypeFilter/ContentTypeFilter.module.css +60 -0
- package/src/components/ContentTypeFilter/contentTypes.js +58 -0
- package/src/components/CookieCli/CookieCli.jsx +223 -0
- package/src/components/CookieCli/CookieCli.module.css +166 -0
- package/src/components/CtaBanner/CtaBanner.jsx +61 -0
- package/src/components/CtaBanner/CtaBanner.module.css +65 -0
- package/src/components/DetailHero/DetailHero.jsx +143 -0
- package/src/components/DetailHero/DetailHero.module.css +154 -0
- package/src/components/Diagrams/Diagrams.jsx +148 -0
- package/src/components/EmployeeCard/EmployeeCard.jsx +127 -0
- package/src/components/EmployeeCard/EmployeeCard.module.css +144 -0
- package/src/components/ExternalAppShelf/ExternalAppShelf.jsx +61 -0
- package/src/components/ExternalAppShelf/ExternalAppShelf.module.css +90 -0
- package/src/components/FAQ/FAQ.jsx +42 -0
- package/src/components/FAQ/FAQ.module.css +74 -0
- package/src/components/FacetedFilters/FacetedFilters.jsx +125 -0
- package/src/components/FacetedFilters/FacetedFilters.module.css +133 -0
- package/src/components/FeatureGrid/FeatureGrid.jsx +94 -0
- package/src/components/FeatureGrid/FeatureGrid.module.css +114 -0
- package/src/components/FeatureList/FeatureList.jsx +54 -0
- package/src/components/FeatureList/FeatureList.module.css +52 -0
- package/src/components/FeaturedCard/FeaturedCard.jsx +101 -0
- package/src/components/FeaturedCard/FeaturedCard.module.css +98 -0
- package/src/components/GameModal/GameModal.jsx +197 -0
- package/src/components/GameModal/GameModal.module.css +184 -0
- package/src/components/Hero/Hero.jsx +101 -0
- package/src/components/Hero/Hero.module.css +95 -0
- package/src/components/HexBackground/HexBackground.jsx +56 -0
- package/src/components/HexBackground/HexBackground.module.css +73 -0
- package/src/components/HexNetwork/HexNetwork.jsx +141 -0
- package/src/components/HexNetwork/HexNetwork.module.css +187 -0
- package/src/components/HexRain/HexRain.jsx +81 -0
- package/src/components/HowSteps/HowSteps.jsx +57 -0
- package/src/components/HowSteps/HowSteps.module.css +52 -0
- package/src/components/ManagedCommonGround/ManagedCommonGround.jsx +78 -0
- package/src/components/ManagedCommonGround/ManagedCommonGround.module.css +16 -0
- package/src/components/NewsletterCta/NewsletterCta.jsx +83 -0
- package/src/components/NewsletterCta/NewsletterCta.module.css +103 -0
- package/src/components/PairCard/PairCard.jsx +58 -0
- package/src/components/PairCard/PairCard.module.css +54 -0
- package/src/components/PartnerCard/PartnerCard.jsx +130 -0
- package/src/components/PartnerCard/PartnerCard.module.css +198 -0
- package/src/components/PartnerDirectory/PartnerDirectory.jsx +122 -0
- package/src/components/PartnerDirectory/PartnerDirectory.module.css +25 -0
- package/src/components/PartnerSidecard/PartnerSidecard.jsx +116 -0
- package/src/components/PartnerSidecard/PartnerSidecard.module.css +185 -0
- package/src/components/Pipeline/Pipeline.jsx +198 -0
- package/src/components/Pipeline/Pipeline.module.css +206 -0
- package/src/components/PlatformDiagram/PlatformDiagram.jsx +110 -0
- package/src/components/PlatformOverview/PlatformOverview.jsx +68 -0
- package/src/components/PlatformOverview/PlatformOverview.module.css +71 -0
- package/src/components/ReferenceCard/ReferenceCard.jsx +44 -0
- package/src/components/ReferenceCard/ReferenceCard.module.css +57 -0
- package/src/components/RelatedPosts/RelatedPosts.jsx +58 -0
- package/src/components/RelatedPosts/RelatedPosts.module.css +51 -0
- package/src/components/RotatingCards/RotatingCards.jsx +98 -0
- package/src/components/RotatingCards/RotatingCards.module.css +153 -0
- package/src/components/Showcase/Showcase.jsx +129 -0
- package/src/components/Showcase/Showcase.module.css +168 -0
- package/src/components/SolutionCard/SolutionCard.jsx +83 -0
- package/src/components/SolutionCard/SolutionCard.module.css +99 -0
- package/src/components/StatsStrip/StatsStrip.jsx +38 -0
- package/src/components/StatsStrip/StatsStrip.module.css +53 -0
- package/src/components/WidgetShelf/WidgetShelf.jsx +67 -0
- package/src/components/WidgetShelf/WidgetShelf.module.css +73 -0
- package/src/components/index.js +96 -0
- package/src/components/primitives/AuthorByline.jsx +85 -0
- package/src/components/primitives/AuthorByline.module.css +57 -0
- package/src/components/primitives/BrandCitation.jsx +71 -0
- package/src/components/primitives/Button.jsx +46 -0
- package/src/components/primitives/Button.module.css +88 -0
- package/src/components/primitives/Card.jsx +42 -0
- package/src/components/primitives/Card.module.css +42 -0
- package/src/components/primitives/Eyebrow.jsx +37 -0
- package/src/components/primitives/Eyebrow.module.css +19 -0
- package/src/components/primitives/HexBullet.jsx +37 -0
- package/src/components/primitives/HexBullet.module.css +16 -0
- package/src/components/primitives/HexThumbnail.jsx +70 -0
- package/src/components/primitives/HexThumbnail.module.css +45 -0
- package/src/components/primitives/Pill.jsx +42 -0
- package/src/components/primitives/Pill.module.css +30 -0
- package/src/components/primitives/Section.jsx +51 -0
- package/src/components/primitives/Section.module.css +31 -0
- package/src/components/primitives/SectionHead.jsx +36 -0
- package/src/components/primitives/SectionHead.module.css +43 -0
- package/src/components/primitives/index.js +22 -0
- package/src/css/brand.css +158 -0
- package/src/css/tokens.css +12 -0
- package/src/data/app-downloads.js +42 -0
- package/src/diagrams/README.md +74 -0
- package/src/diagrams/cn-domain-tree.js +105 -0
- package/src/diagrams/cn-hex-prism.js +163 -0
- package/src/diagrams/cn-hex.js +181 -0
- package/src/diagrams/cn-honeycomb-bg.js +135 -0
- package/src/diagrams/cn-pipeline.js +150 -0
- package/src/diagrams/cn-platform.js +156 -0
- package/src/diagrams/cn-side-box.js +104 -0
- package/src/diagrams/index.js +28 -0
- package/src/index.js +183 -0
- package/src/theme/Footer/index.jsx +516 -0
- package/src/theme/MDXPage/index.jsx +134 -0
- package/src/theme/Navbar/index.jsx +120 -0
- package/src/theme/Navbar/styles.module.css +114 -0
- package/src/theme/brand.jsx +63 -0
- package/src/theme.js +45 -0
- package/src/utils/lazyScript.js +37 -0
- package/static/img/favicon.svg +14 -0
- package/static/img/honeycomb-scatter.svg +23 -0
- package/static/img/honeycomb-watermark.svg +108 -0
- package/static/img/logo-dark.svg +11 -0
- package/static/img/logo.svg +14 -0
- package/static/img/nextcloud-logo.svg +5 -0
- package/static/lib/canal-footer.css +418 -0
- package/static/lib/canal-footer.js +499 -0
- package/static/lib/clients-flow.js +317 -0
- package/static/lib/conduction-bg.css +50 -0
- package/static/lib/conduction-bg.js +122 -0
- package/static/lib/hex-rain.css +128 -0
- package/static/lib/hex-rain.js +284 -0
- package/static/lib/kade-cyclist.css +264 -0
- package/static/lib/kade-cyclist.js +420 -0
- package/static/lib/logo-memory.css +219 -0
- package/static/lib/logo-memory.js +540 -0
- package/static/lib/platform-diagram.css +458 -0
- package/static/lib/platform-diagram.js +414 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <PlatformOverview />
|
|
3
|
+
*
|
|
4
|
+
* Section wrapper around the bespoke <platform-diagram> web component
|
|
5
|
+
* (workspace + corner-hex categories + flow lines). Renders the
|
|
6
|
+
* "section-head" pattern (eyebrow + h2 + lede) above the diagram.
|
|
7
|
+
*
|
|
8
|
+
* The platform-diagram custom element is registered by
|
|
9
|
+
* /lib/platform-diagram.js, which sites must include via <Head> on
|
|
10
|
+
* any page that uses this section. The CSS is similarly served from
|
|
11
|
+
* /lib/platform-diagram.css.
|
|
12
|
+
*
|
|
13
|
+
* Mirrors the .platform section in preview/pages/landing.html.
|
|
14
|
+
*
|
|
15
|
+
* Usage in MDX:
|
|
16
|
+
*
|
|
17
|
+
* import Head from '@docusaurus/Head';
|
|
18
|
+
* import {PlatformOverview} from '@conduction/docusaurus-preset/components';
|
|
19
|
+
*
|
|
20
|
+
* <Head>
|
|
21
|
+
* <link rel="stylesheet" href="/lib/platform-diagram.css" />
|
|
22
|
+
* <script src="/lib/platform-diagram.js" defer />
|
|
23
|
+
* </Head>
|
|
24
|
+
*
|
|
25
|
+
* <PlatformOverview
|
|
26
|
+
* eyebrow="The platform"
|
|
27
|
+
* title={<>Five components.<br/>Twenty-four apps. One <span className="next-blue">Nextcloud</span> workspace.</>}
|
|
28
|
+
* lede={<>...</>}
|
|
29
|
+
* >
|
|
30
|
+
* <platform-diagram>
|
|
31
|
+
* <pd-workspace logo="/img/nextcloud-logo.svg" alt="Nextcloud" role="Workspace" />
|
|
32
|
+
* <pd-list position="top" family="nextcloud">
|
|
33
|
+
* <pd-item name="Files" desc="...">
|
|
34
|
+
* <svg>...</svg>
|
|
35
|
+
* </pd-item>
|
|
36
|
+
* ...
|
|
37
|
+
* </pd-list>
|
|
38
|
+
* ...
|
|
39
|
+
* </platform-diagram>
|
|
40
|
+
* </PlatformOverview>
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
import React from 'react';
|
|
44
|
+
import styles from './PlatformOverview.module.css';
|
|
45
|
+
|
|
46
|
+
export default function PlatformOverview({eyebrow, title, lede, children}) {
|
|
47
|
+
return (
|
|
48
|
+
<section className={styles.section}>
|
|
49
|
+
<div className={styles.inner}>
|
|
50
|
+
{(eyebrow || title || lede) && (
|
|
51
|
+
<div className={styles.head}>
|
|
52
|
+
<div>
|
|
53
|
+
{eyebrow && (
|
|
54
|
+
<div className={styles.eyebrow}>
|
|
55
|
+
<span className={styles.eyebrowHex} aria-hidden="true"></span>
|
|
56
|
+
{eyebrow}
|
|
57
|
+
</div>
|
|
58
|
+
)}
|
|
59
|
+
{title && <h2 className={styles.title}>{title}</h2>}
|
|
60
|
+
</div>
|
|
61
|
+
{lede && <p className={styles.lede}>{lede}</p>}
|
|
62
|
+
</div>
|
|
63
|
+
)}
|
|
64
|
+
{children}
|
|
65
|
+
</div>
|
|
66
|
+
</section>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <PlatformOverview /> styles. Mirrors the .platform section from
|
|
3
|
+
* preview/pages/landing.html (section-head + platform-diagram).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
.section {
|
|
7
|
+
background: white;
|
|
8
|
+
padding: 96px 64px;
|
|
9
|
+
font-family: var(--conduction-typography-font-family-body);
|
|
10
|
+
}
|
|
11
|
+
@media (max-width: 900px) {
|
|
12
|
+
.section { padding: 64px 24px; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.inner {
|
|
16
|
+
max-width: 1280px;
|
|
17
|
+
margin: 0 auto;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.head {
|
|
21
|
+
display: grid;
|
|
22
|
+
grid-template-columns: 1.1fr 1fr;
|
|
23
|
+
gap: 48px;
|
|
24
|
+
align-items: end;
|
|
25
|
+
margin-bottom: 64px;
|
|
26
|
+
}
|
|
27
|
+
@media (max-width: 900px) {
|
|
28
|
+
.head { grid-template-columns: 1fr; gap: 24px; margin-bottom: 48px; }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.eyebrow {
|
|
32
|
+
display: inline-flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
gap: 10px;
|
|
35
|
+
font-family: var(--conduction-typography-font-family-code);
|
|
36
|
+
font-size: 12px;
|
|
37
|
+
letter-spacing: 0.1em;
|
|
38
|
+
text-transform: uppercase;
|
|
39
|
+
color: var(--c-cobalt-400);
|
|
40
|
+
margin-bottom: 16px;
|
|
41
|
+
}
|
|
42
|
+
.eyebrowHex {
|
|
43
|
+
width: 12px;
|
|
44
|
+
height: 14px;
|
|
45
|
+
clip-path: var(--hex-pointy-top);
|
|
46
|
+
background: var(--c-orange-knvb);
|
|
47
|
+
display: inline-block;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.title {
|
|
51
|
+
font-size: 44px;
|
|
52
|
+
font-weight: 700;
|
|
53
|
+
line-height: 1.05;
|
|
54
|
+
letter-spacing: -0.02em;
|
|
55
|
+
color: var(--c-blue-cobalt);
|
|
56
|
+
margin: 0;
|
|
57
|
+
max-width: 16ch;
|
|
58
|
+
}
|
|
59
|
+
@media (max-width: 700px) {
|
|
60
|
+
.title { font-size: 32px; }
|
|
61
|
+
}
|
|
62
|
+
.title :global(.next-blue) { color: var(--c-nextcloud-blue); }
|
|
63
|
+
|
|
64
|
+
.lede {
|
|
65
|
+
font-size: 16px;
|
|
66
|
+
line-height: 1.55;
|
|
67
|
+
color: var(--c-cobalt-700);
|
|
68
|
+
margin: 0;
|
|
69
|
+
max-width: 50ch;
|
|
70
|
+
}
|
|
71
|
+
.lede :global(.next-blue) { color: var(--c-nextcloud-blue); }
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <ReferenceCard /> + <ReferenceGrid />
|
|
3
|
+
*
|
|
4
|
+
* Customer-reference card from preview/components/reference-cards.html.
|
|
5
|
+
* Used on partner detail pages and the /references section.
|
|
6
|
+
*
|
|
7
|
+
* Visual structure:
|
|
8
|
+
* ┌─────────────────────────────┐
|
|
9
|
+
* │ [SECTOR-TAG] │
|
|
10
|
+
* │ Customer name │
|
|
11
|
+
* │ What we did paragraph │
|
|
12
|
+
* │ ────────── │
|
|
13
|
+
* │ ⬢ App ⬢ App ⬢ App │
|
|
14
|
+
* └─────────────────────────────┘
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import React from 'react';
|
|
18
|
+
import HexBullet from '../primitives/HexBullet';
|
|
19
|
+
import styles from './ReferenceCard.module.css';
|
|
20
|
+
|
|
21
|
+
export function ReferenceGrid({columns = 3, children, className}) {
|
|
22
|
+
const composed = [styles.grid, styles['cols-' + columns], className].filter(Boolean).join(' ');
|
|
23
|
+
return <div className={composed}>{children}</div>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default function ReferenceCard({sector, name, what, stack = [], className}) {
|
|
27
|
+
return (
|
|
28
|
+
<div className={[styles.card, className].filter(Boolean).join(' ')}>
|
|
29
|
+
{sector && <span className={styles.sectorTag}>{sector}</span>}
|
|
30
|
+
{name && <h4 className={styles.name}>{name}</h4>}
|
|
31
|
+
{what && <p className={styles.what}>{what}</p>}
|
|
32
|
+
{stack.length > 0 && (
|
|
33
|
+
<div className={styles.stack}>
|
|
34
|
+
{stack.map((app, i) => (
|
|
35
|
+
<span key={i} className={styles.pill}>
|
|
36
|
+
<HexBullet size="sm" color="var(--c-blue-cobalt)" />
|
|
37
|
+
{app}
|
|
38
|
+
</span>
|
|
39
|
+
))}
|
|
40
|
+
</div>
|
|
41
|
+
)}
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <ReferenceCard /> styles. Mirrors reference-cards.css exactly.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
.grid { display: grid; gap: 16px; }
|
|
6
|
+
.cols-2 { grid-template-columns: repeat(2, 1fr); }
|
|
7
|
+
.cols-3 { grid-template-columns: repeat(3, 1fr); }
|
|
8
|
+
@media (max-width: 900px) { .grid { grid-template-columns: 1fr; } }
|
|
9
|
+
|
|
10
|
+
.card {
|
|
11
|
+
background: white;
|
|
12
|
+
border: 1px solid var(--c-cobalt-100);
|
|
13
|
+
border-radius: var(--radius-lg);
|
|
14
|
+
padding: 24px;
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
gap: 12px;
|
|
18
|
+
font-family: var(--conduction-typography-font-family-body);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.sectorTag {
|
|
22
|
+
display: inline-flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
gap: 6px;
|
|
25
|
+
font-family: var(--conduction-typography-font-family-code);
|
|
26
|
+
font-size: 10px;
|
|
27
|
+
letter-spacing: 0.1em;
|
|
28
|
+
text-transform: uppercase;
|
|
29
|
+
color: var(--c-cobalt-700);
|
|
30
|
+
background: var(--c-cobalt-50);
|
|
31
|
+
padding: 4px 10px;
|
|
32
|
+
border-radius: var(--radius-pill);
|
|
33
|
+
align-self: flex-start;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.name { font-size: 17px; font-weight: 700; margin: 0; color: var(--c-cobalt-900); }
|
|
37
|
+
.what { font-size: 14px; color: var(--c-cobalt-700); line-height: 1.5; margin: 0; }
|
|
38
|
+
|
|
39
|
+
.stack {
|
|
40
|
+
display: flex;
|
|
41
|
+
gap: 6px;
|
|
42
|
+
flex-wrap: wrap;
|
|
43
|
+
padding-top: 10px;
|
|
44
|
+
border-top: 1px solid var(--c-cobalt-100);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.pill {
|
|
48
|
+
display: inline-flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
gap: 6px;
|
|
51
|
+
background: var(--c-cobalt-50);
|
|
52
|
+
color: var(--c-cobalt-700);
|
|
53
|
+
padding: 3px 9px;
|
|
54
|
+
border-radius: var(--radius-pill);
|
|
55
|
+
font-size: 11px;
|
|
56
|
+
font-family: var(--conduction-typography-font-family-code);
|
|
57
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <RelatedPosts />
|
|
3
|
+
*
|
|
4
|
+
* Section block used at the bottom of every academy detail page (and
|
|
5
|
+
* sometimes on the landing) to surface a few more posts. A "Keep
|
|
6
|
+
* learning…" heading on the left, a "View all" pill link on the right,
|
|
7
|
+
* a content-card grid below.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors the .related-posts section in preview/components/academy.html.
|
|
10
|
+
*
|
|
11
|
+
* Usage in MDX:
|
|
12
|
+
*
|
|
13
|
+
* <RelatedPosts
|
|
14
|
+
* title="Keep learning…"
|
|
15
|
+
* viewAllHref="/"
|
|
16
|
+
* viewAllLabel="View all"
|
|
17
|
+
* columns={2}
|
|
18
|
+
* >
|
|
19
|
+
* <ContentCard ... />
|
|
20
|
+
* <ContentCard ... />
|
|
21
|
+
* </RelatedPosts>
|
|
22
|
+
*
|
|
23
|
+
* Or, instead of children, pass `items` as an array of ContentCard
|
|
24
|
+
* props for a fully data-driven render.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import React from 'react';
|
|
28
|
+
import ContentCard, {ContentCardGrid} from '../ContentCard/ContentCard';
|
|
29
|
+
import styles from './RelatedPosts.module.css';
|
|
30
|
+
|
|
31
|
+
export default function RelatedPosts({
|
|
32
|
+
title = 'Keep learning…',
|
|
33
|
+
viewAllHref,
|
|
34
|
+
viewAllLabel = 'View all',
|
|
35
|
+
columns = 2,
|
|
36
|
+
items,
|
|
37
|
+
children,
|
|
38
|
+
className,
|
|
39
|
+
}) {
|
|
40
|
+
return (
|
|
41
|
+
<section className={[styles.section, className].filter(Boolean).join(' ')}>
|
|
42
|
+
<div className={styles.head}>
|
|
43
|
+
<h2 className={styles.title}>{title}</h2>
|
|
44
|
+
{viewAllHref && (
|
|
45
|
+
<a href={viewAllHref} className={styles.link}>
|
|
46
|
+
{viewAllLabel}
|
|
47
|
+
</a>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<ContentCardGrid columns={columns}>
|
|
52
|
+
{items
|
|
53
|
+
? items.map((it, i) => <ContentCard key={it.href || i} {...it} />)
|
|
54
|
+
: children}
|
|
55
|
+
</ContentCardGrid>
|
|
56
|
+
</section>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <RelatedPosts /> styles. Mirrors .related-posts in
|
|
3
|
+
* preview/components/academy.css.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
.section {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: var(--space-8);
|
|
10
|
+
font-family: var(--conduction-typography-font-family-body);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.head {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: baseline;
|
|
16
|
+
justify-content: space-between;
|
|
17
|
+
gap: var(--space-6);
|
|
18
|
+
flex-wrap: wrap;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.title {
|
|
22
|
+
font-size: 36px;
|
|
23
|
+
font-weight: 700;
|
|
24
|
+
letter-spacing: -0.02em;
|
|
25
|
+
color: var(--c-cobalt-900);
|
|
26
|
+
margin: 0;
|
|
27
|
+
line-height: 1.1;
|
|
28
|
+
}
|
|
29
|
+
@media (max-width: 700px) { .title { font-size: 28px; } }
|
|
30
|
+
|
|
31
|
+
.link {
|
|
32
|
+
display: inline-flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
padding: 10px 22px;
|
|
35
|
+
background: var(--c-blue-cobalt);
|
|
36
|
+
color: white;
|
|
37
|
+
font-family: var(--conduction-typography-font-family-code);
|
|
38
|
+
font-size: 12px;
|
|
39
|
+
letter-spacing: 0.1em;
|
|
40
|
+
text-transform: uppercase;
|
|
41
|
+
font-weight: 600;
|
|
42
|
+
border-radius: var(--radius-pill);
|
|
43
|
+
text-decoration: none;
|
|
44
|
+
flex-shrink: 0;
|
|
45
|
+
transition: background 120ms ease;
|
|
46
|
+
}
|
|
47
|
+
.link:hover {
|
|
48
|
+
background: var(--c-cobalt-700);
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
color: white;
|
|
51
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <RotatingCards />
|
|
3
|
+
*
|
|
4
|
+
* Scroll-pinned stacked cards, after honeycomb.io home "What
|
|
5
|
+
* Honeycomb helps you do". Each card sticks to the top of the
|
|
6
|
+
* viewport as you scroll past, the next card slides up from below to
|
|
7
|
+
* cover it, so the surface advances by scrolling instead of by click
|
|
8
|
+
* or auto-rotation. No timer, no carousel, no pagination.
|
|
9
|
+
*
|
|
10
|
+
* Per-card layout:
|
|
11
|
+
* ┌────────────────────────────┬────────────────────────┐
|
|
12
|
+
* │ │ │
|
|
13
|
+
* │ [coloured panel] │ [white text panel] │
|
|
14
|
+
* │ │ │
|
|
15
|
+
* │ abstract product mock │ eyebrow │
|
|
16
|
+
* │ on a hex backdrop │ title │
|
|
17
|
+
* │ │ summary │
|
|
18
|
+
* │ │ cta │
|
|
19
|
+
* └────────────────────────────┴────────────────────────┘
|
|
20
|
+
*
|
|
21
|
+
* Each card carries a tone (mint, lavender, terracotta, forest,
|
|
22
|
+
* coral, workspace) that drives the coloured-panel side. The text
|
|
23
|
+
* side stays white throughout for legibility.
|
|
24
|
+
*
|
|
25
|
+
* Usage in MDX:
|
|
26
|
+
*
|
|
27
|
+
* <RotatingCards
|
|
28
|
+
* eyebrow="What Conduction helps you do"
|
|
29
|
+
* title="Six things, in two minutes."
|
|
30
|
+
* cards={[
|
|
31
|
+
* {
|
|
32
|
+
* tone: 'forest',
|
|
33
|
+
* eyebrow: 'See everything',
|
|
34
|
+
* title: 'Publish a public catalogue.',
|
|
35
|
+
* summary: '...',
|
|
36
|
+
* cta: {label: 'See OpenCatalogi', href: '/apps/opencatalogi'},
|
|
37
|
+
* panel: <AppMock app="opencatalogi" />,
|
|
38
|
+
* },
|
|
39
|
+
* ...
|
|
40
|
+
* ]}
|
|
41
|
+
* />
|
|
42
|
+
*
|
|
43
|
+
* Implementation note: each card is `position: sticky; top: <stagger>`,
|
|
44
|
+
* staggered so card N+1 ends up slightly above card N when both are
|
|
45
|
+
* pinned. The total scroll distance is sized by the wrapper's height
|
|
46
|
+
* (one viewport per card minus the stagger).
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
import React from 'react';
|
|
50
|
+
import HexBackground from '../HexBackground/HexBackground.jsx';
|
|
51
|
+
import styles from './RotatingCards.module.css';
|
|
52
|
+
|
|
53
|
+
export default function RotatingCards({
|
|
54
|
+
eyebrow,
|
|
55
|
+
title,
|
|
56
|
+
lede,
|
|
57
|
+
cards = [],
|
|
58
|
+
className,
|
|
59
|
+
}) {
|
|
60
|
+
if (cards.length === 0) return null;
|
|
61
|
+
return (
|
|
62
|
+
<section className={[styles.root, className].filter(Boolean).join(' ')}>
|
|
63
|
+
{(eyebrow || title || lede) && (
|
|
64
|
+
<header className={styles.head}>
|
|
65
|
+
{eyebrow && <div className={styles.eyebrow}><span className={styles.h}></span>{eyebrow}</div>}
|
|
66
|
+
{title && <h2 className={styles.title}>{title}</h2>}
|
|
67
|
+
{lede && <p className={styles.lede}>{lede}</p>}
|
|
68
|
+
</header>
|
|
69
|
+
)}
|
|
70
|
+
<div className={styles.stack} style={{'--stack-count': cards.length}}>
|
|
71
|
+
{cards.map((card, i) => (
|
|
72
|
+
<article
|
|
73
|
+
key={i}
|
|
74
|
+
className={[styles.card, styles[`tone-${card.tone || 'cobalt'}`]].join(' ')}
|
|
75
|
+
style={{'--i': i, top: `calc(var(--card-top, 80px) + ${i * 24}px)`}}
|
|
76
|
+
>
|
|
77
|
+
<div className={styles.cardImage}>
|
|
78
|
+
<HexBackground tone={`${card.tone || 'cobalt'}-100`} position="top" size="lg" density={2} />
|
|
79
|
+
<div className={styles.cardImageInner}>
|
|
80
|
+
{card.panel}
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
<div className={styles.cardText}>
|
|
84
|
+
{card.eyebrow && <div className={styles.cardEyebrow}>{card.eyebrow}</div>}
|
|
85
|
+
{card.title && <h3 className={styles.cardTitle}>{card.title}</h3>}
|
|
86
|
+
{card.summary && <p className={styles.cardSummary}>{card.summary}</p>}
|
|
87
|
+
{card.cta && (
|
|
88
|
+
<a href={card.cta.href} className={styles.cardCta}>
|
|
89
|
+
{card.cta.label}
|
|
90
|
+
</a>
|
|
91
|
+
)}
|
|
92
|
+
</div>
|
|
93
|
+
</article>
|
|
94
|
+
))}
|
|
95
|
+
</div>
|
|
96
|
+
</section>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <RotatingCards /> styles. Scroll-pinned stacked cards.
|
|
3
|
+
*
|
|
4
|
+
* Each card is position: sticky and stays pinned at top: calc(...) as
|
|
5
|
+
* the viewport scrolls past it. Cards stagger by 24px each so that
|
|
6
|
+
* when card N is pinned and the user keeps scrolling, card N+1 slides
|
|
7
|
+
* up from below and ends 24px lower than card N — readable as a
|
|
8
|
+
* stack, not a swap.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
.root {
|
|
12
|
+
max-width: 1280px;
|
|
13
|
+
margin: 0 auto;
|
|
14
|
+
padding: var(--space-12) var(--space-12);
|
|
15
|
+
font-family: var(--conduction-typography-font-family-body);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* ---------- Header ---------- */
|
|
19
|
+
.head { max-width: 70ch; margin: 0 0 var(--space-8); }
|
|
20
|
+
.eyebrow {
|
|
21
|
+
display: inline-flex; align-items: center; gap: var(--space-2);
|
|
22
|
+
font-family: var(--conduction-typography-font-family-code);
|
|
23
|
+
font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase;
|
|
24
|
+
color: var(--c-orange-knvb);
|
|
25
|
+
margin-bottom: var(--space-3);
|
|
26
|
+
}
|
|
27
|
+
.eyebrow .h { width: 10px; height: 12px; clip-path: var(--hex-pointy-top); background: var(--c-orange-knvb); }
|
|
28
|
+
.title {
|
|
29
|
+
font-size: 40px; font-weight: 700; letter-spacing: -0.02em;
|
|
30
|
+
line-height: 1.1; color: var(--c-cobalt-900); margin: 0 0 var(--space-3);
|
|
31
|
+
}
|
|
32
|
+
.lede { font-size: 17px; line-height: 1.5; color: var(--c-cobalt-700); margin: 0; }
|
|
33
|
+
|
|
34
|
+
/* ---------- The stack ---------- */
|
|
35
|
+
.stack {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
gap: 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.card {
|
|
42
|
+
position: sticky;
|
|
43
|
+
/* `top` is set inline as `calc(var(--card-top, 80px) + i * 24px)` so
|
|
44
|
+
each pinned card lands a little lower than the previous one. */
|
|
45
|
+
display: grid;
|
|
46
|
+
/* Image side leans wider so the AppMock has room to breathe;
|
|
47
|
+
text side stays narrower for a comfortable measure. The gap
|
|
48
|
+
between them shows the card's white background as a clean
|
|
49
|
+
gutter, so the coloured image panel and the white text panel
|
|
50
|
+
feel like two distinct planes instead of one fused block. */
|
|
51
|
+
grid-template-columns: 1.15fr 1fr;
|
|
52
|
+
gap: var(--space-8);
|
|
53
|
+
background: white;
|
|
54
|
+
border: 1px solid var(--c-cobalt-100);
|
|
55
|
+
border-radius: var(--radius-xl);
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
box-shadow: var(--shadow-2);
|
|
58
|
+
margin-bottom: var(--space-4);
|
|
59
|
+
/* Each card needs at least one viewport-height of scroll room before
|
|
60
|
+
the next card can pin over it. min-height drives that. */
|
|
61
|
+
min-height: 480px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@media (max-width: 900px) {
|
|
65
|
+
.card { grid-template-columns: 1fr; min-height: auto; }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ---------- Image side (coloured panel) — full-bleed to all edges
|
|
69
|
+
so the colour clearly demarcates the panel from the white text
|
|
70
|
+
side. The AppMock floats centred on the colour; padding lives on
|
|
71
|
+
the inner wrapper, not on the panel itself. ---------- */
|
|
72
|
+
.cardImage {
|
|
73
|
+
position: relative;
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: center;
|
|
78
|
+
padding: 0;
|
|
79
|
+
min-height: 380px;
|
|
80
|
+
}
|
|
81
|
+
.cardImageInner {
|
|
82
|
+
position: relative;
|
|
83
|
+
z-index: 1;
|
|
84
|
+
width: 100%;
|
|
85
|
+
display: flex; align-items: center; justify-content: center;
|
|
86
|
+
padding: var(--space-8) var(--space-6);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Tone palettes — set the .cardImage background. */
|
|
90
|
+
.tone-mint .cardImage { background: var(--c-mint-100); }
|
|
91
|
+
.tone-mint .cardEyebrow,
|
|
92
|
+
.tone-mint .cardCta { color: var(--c-mint-700); }
|
|
93
|
+
|
|
94
|
+
.tone-lavender .cardImage { background: var(--c-lavender-100); }
|
|
95
|
+
.tone-lavender .cardEyebrow,
|
|
96
|
+
.tone-lavender .cardCta { color: var(--c-lavender-700); }
|
|
97
|
+
|
|
98
|
+
.tone-forest .cardImage { background: var(--c-forest-100); }
|
|
99
|
+
.tone-forest .cardEyebrow,
|
|
100
|
+
.tone-forest .cardCta { color: var(--c-forest-700); }
|
|
101
|
+
|
|
102
|
+
.tone-terracotta .cardImage { background: var(--c-terracotta-100); }
|
|
103
|
+
.tone-terracotta .cardEyebrow,
|
|
104
|
+
.tone-terracotta .cardCta { color: var(--c-terracotta-700); }
|
|
105
|
+
|
|
106
|
+
.tone-coral .cardImage { background: var(--c-coral-100); }
|
|
107
|
+
.tone-coral .cardEyebrow,
|
|
108
|
+
.tone-coral .cardCta { color: var(--c-coral-700); }
|
|
109
|
+
|
|
110
|
+
.tone-workspace .cardImage { background: var(--c-workspace-100); }
|
|
111
|
+
.tone-workspace .cardEyebrow,
|
|
112
|
+
.tone-workspace .cardCta { color: var(--c-cobalt-700); }
|
|
113
|
+
|
|
114
|
+
.tone-cobalt .cardImage { background: var(--c-cobalt-50); }
|
|
115
|
+
.tone-cobalt .cardEyebrow,
|
|
116
|
+
.tone-cobalt .cardCta { color: var(--c-blue-cobalt); }
|
|
117
|
+
|
|
118
|
+
/* ---------- Text side ---------- */
|
|
119
|
+
.cardText {
|
|
120
|
+
display: flex;
|
|
121
|
+
flex-direction: column;
|
|
122
|
+
gap: var(--space-4);
|
|
123
|
+
padding: var(--space-10) var(--space-9);
|
|
124
|
+
justify-content: center;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.cardEyebrow {
|
|
128
|
+
font-family: var(--conduction-typography-font-family-code);
|
|
129
|
+
font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase;
|
|
130
|
+
font-weight: 600;
|
|
131
|
+
}
|
|
132
|
+
.cardTitle {
|
|
133
|
+
font-size: 32px; font-weight: 700; letter-spacing: -0.02em;
|
|
134
|
+
line-height: 1.15; color: var(--c-cobalt-900); margin: 0;
|
|
135
|
+
}
|
|
136
|
+
.cardSummary {
|
|
137
|
+
font-size: 17px; line-height: 1.55; color: var(--c-cobalt-700);
|
|
138
|
+
margin: 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.cardCta {
|
|
142
|
+
align-self: flex-start;
|
|
143
|
+
display: inline-flex; align-items: center;
|
|
144
|
+
background: var(--c-blue-cobalt); color: white !important;
|
|
145
|
+
padding: 10px 18px;
|
|
146
|
+
border-radius: var(--radius-md);
|
|
147
|
+
font-size: 13px; font-weight: 600; letter-spacing: 0.04em;
|
|
148
|
+
text-transform: uppercase;
|
|
149
|
+
text-decoration: none;
|
|
150
|
+
transition: background 160ms;
|
|
151
|
+
margin-top: var(--space-2);
|
|
152
|
+
}
|
|
153
|
+
.cardCta:hover { background: var(--c-cobalt-700); }
|