@conduction/docusaurus-preset 2.10.2 → 3.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.
@@ -84,7 +84,6 @@ Thin React wrappers around the framework-agnostic web components in
84
84
  slot-based children pass through. All exported from `Diagrams/Diagrams.jsx`.
85
85
 
86
86
  - **Hex** wraps `<cn-hex>` (color, size, variant, layout, interactive)
87
- - **HexPrism** wraps `<cn-hex-prism>` (family, size, state)
88
87
  - **Platform** wraps `<cn-platform>` (ground)
89
88
  - **DomainTree** wraps `<cn-domain-tree>`
90
89
  - **DiagramPipeline** wraps `<cn-pipeline>` (renamed from Pipeline to avoid the components/Pipeline name collision)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conduction/docusaurus-preset",
3
- "version": "2.10.2",
3
+ "version": "3.1.0",
4
4
  "scripts": {
5
5
  "prepack": "node scripts/prepack-bundle-css.js"
6
6
  },
@@ -223,13 +223,13 @@
223
223
  display: inline-flex; align-items: center; gap: 3px;
224
224
  padding: 2px 6px;
225
225
  border-radius: 999px;
226
- background: var(--c-mint-100);
226
+ background: var(--c-mint-300);
227
227
  }
228
228
  .am .statusPill .h { width: 6px; height: 7px; clip-path: var(--hex-pointy-top); background: var(--c-mint-500); }
229
- .am .statusPill .t { height: 3px; width: 22px; background: var(--c-mint-700); border-radius: 1px; }
230
- .am .statusPill.beta { background: var(--c-coral-50); }
229
+ .am .statusPill .t { height: 3px; width: 22px; background: var(--c-mint-500); border-radius: 1px; }
230
+ .am .statusPill.beta { background: var(--c-coral-300); }
231
231
  .am .statusPill.beta .h { background: var(--c-orange-knvb); }
232
- .am .statusPill.beta .t { background: var(--c-coral-700); }
232
+ .am .statusPill.beta .t { background: var(--c-coral-500); }
233
233
 
234
234
  /* KPI strip cell — big number left, label right. */
235
235
  .am .kpi {
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Thin React wrappers for the framework-agnostic diagram web
3
- * components in @conduction/diagrams: <cn-hex>, <cn-hex-prism>,
4
- * <cn-platform>, <cn-domain-tree>, etc.
3
+ * components in @conduction/diagrams: <cn-hex>, <cn-platform>,
4
+ * <cn-domain-tree>, etc. Brand is flat-hex only; the 3D prism was
5
+ * removed in v3.0.0.
5
6
  *
6
7
  * Why React wrappers around already-working web components?
7
8
  * - Type-checked prop names (no remembering "size" vs "scale")
@@ -16,18 +17,13 @@
16
17
  *
17
18
  * Usage in MDX:
18
19
  *
19
- * import {Hex, HexPrism} from '@conduction/docusaurus-preset/components';
20
+ * import {Hex} from '@conduction/docusaurus-preset/components';
20
21
  *
21
22
  * <Hex color="cobalt" size="md" variant="solid">
22
23
  * <span slot="kicker">DATA</span>
23
24
  * OpenRegister
24
25
  * </Hex>
25
26
  *
26
- * <HexPrism family="coral" size="lg" state="hover">
27
- * <span slot="kicker">CATALOG</span>
28
- * OpenCatalogi
29
- * </HexPrism>
30
- *
31
27
  * The runtime is lazy-loaded once, then customElements.define guards
32
28
  * keep subsequent imports a no-op. If the package isn't installed
33
29
  * (non-Conduction sites), the import fails silently and the elements
@@ -79,19 +75,6 @@ export function Hex({color, size, variant, layout, interactive, children, ...res
79
75
  );
80
76
  }
81
77
 
82
- /* ============================================================
83
- <HexPrism /> wraps <cn-hex-prism>
84
- Observed: family, size, state
85
- ============================================================ */
86
- export function HexPrism({family, size, state, children, ...rest}) {
87
- useDiagramRuntime();
88
- return (
89
- <cn-hex-prism {...attrs({family, size, state})} {...rest}>
90
- {children}
91
- </cn-hex-prism>
92
- );
93
- }
94
-
95
78
  /* ============================================================
96
79
  <Platform /> wraps <cn-platform>
97
80
  Slot-based: a centre apex + surrounding hexes/prisms as children.
@@ -24,12 +24,12 @@
24
24
  .tone-cobalt-100 .hexA { background: var(--c-cobalt-100); }
25
25
  .tone-cobalt-50 .hexA { background: var(--c-cobalt-50); }
26
26
  .tone-cobalt-700 .hexA { background: var(--c-cobalt-700); }
27
- .tone-mint-100 .hexA { background: var(--c-mint-100); }
28
- .tone-lavender-100 .hexA { background: var(--c-lavender-100); }
29
- .tone-forest-100 .hexA { background: var(--c-forest-100); }
30
- .tone-terracotta-100 .hexA { background: var(--c-terracotta-100); }
31
- .tone-coral-100 .hexA { background: var(--c-coral-100); }
32
- .tone-workspace-100 .hexA { background: var(--c-workspace-100); }
27
+ .tone-mint-100 .hexA { background: var(--c-mint-300); }
28
+ .tone-lavender-100 .hexA { background: var(--c-lavender-300); }
29
+ .tone-forest-100 .hexA { background: var(--c-forest-300); }
30
+ .tone-terracotta-100 .hexA { background: var(--c-terracotta-300); }
31
+ .tone-coral-100 .hexA { background: var(--c-coral-300); }
32
+ .tone-workspace-100 .hexA { background: var(--c-workspace-300); }
33
33
 
34
34
  /* The second hex (density=2) carries a darker tone of the same family
35
35
  for layered depth. */
@@ -0,0 +1,157 @@
1
+ /**
2
+ * <LeafCard /> + <LeafGrid />
3
+ *
4
+ * Metadata header for an Open Register leaf integration. Mirrors the
5
+ * registry descriptor (id, label, icon, group, requiredApp, storage)
6
+ * so every per-leaf docs page leads with the same compact summary —
7
+ * one card, six fields, no prose to skim. Used at the top of every
8
+ * docs/Integrations/{leaf}.md page in the openregister docs site.
9
+ *
10
+ * Used on:
11
+ * - /docs/Integrations/{leaf} (one <LeafCard />)
12
+ * - /docs/Integrations/leaf-system (a <LeafGrid /> of all 18+1)
13
+ *
14
+ * Brand:
15
+ * - Pointy-top hex carries the leaf's MDI icon (cobalt by default,
16
+ * orange for the one accent-leaf when grouped). Falls back to the
17
+ * `id` initial when no icon is given.
18
+ * - Status pill colours: green = backend-ready, amber = stub,
19
+ * cobalt = external (OpenConnector-routed), grey = built-in.
20
+ *
21
+ * Usage in MDX:
22
+ *
23
+ * import {LeafCard} from '@conduction/docusaurus-preset/components';
24
+ *
25
+ * <LeafCard
26
+ * id="calendar"
27
+ * label="Meetings"
28
+ * icon="Calendar"
29
+ * group="comms"
30
+ * requiredApp="calendar"
31
+ * storage="link-table"
32
+ * status="backend-ready" />
33
+ *
34
+ * <LeafGrid /> renders a responsive grid of LeafCard children for
35
+ * the overview page:
36
+ *
37
+ * <LeafGrid>
38
+ * <LeafCard id="calendar" ... />
39
+ * <LeafCard id="contacts" ... />
40
+ * </LeafGrid>
41
+ */
42
+
43
+ import React from 'react';
44
+ import styles from './LeafCard.module.css';
45
+
46
+ const STATUS_LABELS = {
47
+ 'backend-ready': 'Backend ready',
48
+ 'stub': 'Provider stub',
49
+ 'external': 'External (OpenConnector)',
50
+ 'built-in': 'Built-in',
51
+ };
52
+
53
+ const GROUP_LABELS = {
54
+ 'core': 'Core',
55
+ 'comms': 'Communication',
56
+ 'docs': 'Documents',
57
+ 'workflow': 'Workflow',
58
+ 'external': 'External',
59
+ };
60
+
61
+ const STORAGE_LABELS = {
62
+ 'magic-column': 'Magic column',
63
+ 'link-table': 'Link table',
64
+ 'external': 'External (no local store)',
65
+ 'query-time': 'Query-time (live)',
66
+ };
67
+
68
+ /**
69
+ * Render a single MDI icon glyph by name, with a graceful fallback
70
+ * to the first letter of the leaf id when the icon name is unknown.
71
+ * The docs site doesn't ship the full MDI set, so unknown icons fall
72
+ * back to a text initial rather than 404'ing on a missing asset.
73
+ */
74
+ function LeafGlyph({icon, id}) {
75
+ if (icon) {
76
+ // Defer the actual icon rendering to the consuming docs site
77
+ // (which can swizzle this if it wires up vue-material-design-icons
78
+ // or any equivalent React icon pack). Default: render the icon
79
+ // name as a small uppercase tag so the page still reads.
80
+ return <span className={styles.iconText} aria-hidden="true">{icon.charAt(0)}</span>;
81
+ }
82
+ return <span className={styles.iconText} aria-hidden="true">{(id || '?').charAt(0).toUpperCase()}</span>;
83
+ }
84
+
85
+ export function LeafCard({
86
+ id,
87
+ label,
88
+ icon,
89
+ group,
90
+ requiredApp,
91
+ storage,
92
+ status,
93
+ href,
94
+ description,
95
+ className,
96
+ }) {
97
+ const statusLabel = STATUS_LABELS[status] || status;
98
+ const groupLabel = GROUP_LABELS[group] || group;
99
+ const storageLabel = STORAGE_LABELS[storage] || storage;
100
+ const composed = [styles.card, styles['status-' + (status || 'unknown')], className].filter(Boolean).join(' ');
101
+
102
+ const inner = (
103
+ <>
104
+ <div className={styles.head}>
105
+ <div className={styles.hex} aria-hidden="true">
106
+ <LeafGlyph icon={icon} id={id} />
107
+ </div>
108
+ <div className={styles.heading}>
109
+ <div className={styles.label}>{label}</div>
110
+ <code className={styles.id}>{id}</code>
111
+ </div>
112
+ {status && <span className={styles.statusPill}>{statusLabel}</span>}
113
+ </div>
114
+ {description && <p className={styles.description}>{description}</p>}
115
+ <dl className={styles.meta}>
116
+ {group && (
117
+ <>
118
+ <dt>Group</dt>
119
+ <dd>{groupLabel}</dd>
120
+ </>
121
+ )}
122
+ {requiredApp !== undefined && (
123
+ <>
124
+ <dt>Required app</dt>
125
+ <dd>{requiredApp ? <code>{requiredApp}</code> : <span className={styles.muted}>None (always available)</span>}</dd>
126
+ </>
127
+ )}
128
+ {storage && (
129
+ <>
130
+ <dt>Storage</dt>
131
+ <dd>{storageLabel}</dd>
132
+ </>
133
+ )}
134
+ {icon && (
135
+ <>
136
+ <dt>Icon</dt>
137
+ <dd><code>{icon}</code></dd>
138
+ </>
139
+ )}
140
+ </dl>
141
+ </>
142
+ );
143
+
144
+ // Render as link when href is set so leaves on the overview grid
145
+ // navigate to their dedicated page on click.
146
+ if (href) {
147
+ return <a href={href} className={composed}>{inner}</a>;
148
+ }
149
+ return <div className={composed}>{inner}</div>;
150
+ }
151
+
152
+ export function LeafGrid({columns = 3, children, className}) {
153
+ const composed = [styles.grid, styles['grid-' + columns], className].filter(Boolean).join(' ');
154
+ return <div className={composed}>{children}</div>;
155
+ }
156
+
157
+ export default LeafCard;
@@ -0,0 +1,153 @@
1
+ /* LeafCard — per-leaf metadata header.
2
+ Pointy-top hex + label + status pill + meta grid. Sized for both
3
+ single-card placement at the top of a docs page and grid placement
4
+ on the overview. */
5
+
6
+ .card {
7
+ display: block;
8
+ background: white;
9
+ border: 1px solid var(--c-cobalt-100);
10
+ border-radius: var(--radius-md);
11
+ padding: var(--space-5);
12
+ text-decoration: none;
13
+ color: inherit;
14
+ transition: border-color 120ms ease, transform 120ms ease;
15
+ }
16
+
17
+ a.card:hover {
18
+ border-color: var(--c-cobalt-400);
19
+ transform: translateY(-1px);
20
+ }
21
+
22
+ .head {
23
+ display: flex;
24
+ align-items: center;
25
+ gap: var(--space-4);
26
+ margin-bottom: var(--space-3);
27
+ }
28
+
29
+ .hex {
30
+ width: 40px;
31
+ height: 46px;
32
+ clip-path: var(--hex-pointy-top);
33
+ background: var(--c-cobalt-50);
34
+ color: var(--c-cobalt-700);
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ flex-shrink: 0;
39
+ font-weight: 700;
40
+ font-size: 16px;
41
+ }
42
+
43
+ .iconText {
44
+ display: inline-block;
45
+ font-weight: 700;
46
+ font-size: 18px;
47
+ }
48
+
49
+ .heading {
50
+ flex: 1;
51
+ min-width: 0;
52
+ }
53
+
54
+ .label {
55
+ font-size: 18px;
56
+ font-weight: 700;
57
+ color: var(--c-cobalt-900);
58
+ margin: 0;
59
+ line-height: 1.2;
60
+ }
61
+
62
+ .id {
63
+ display: inline-block;
64
+ font-size: 12px;
65
+ color: var(--c-cobalt-400);
66
+ font-family: var(--conduction-typography-font-family-code);
67
+ margin-top: 2px;
68
+ }
69
+
70
+ .statusPill {
71
+ display: inline-block;
72
+ font-size: 11px;
73
+ font-weight: 600;
74
+ text-transform: uppercase;
75
+ letter-spacing: 0.06em;
76
+ padding: 4px 10px;
77
+ border-radius: 999px;
78
+ flex-shrink: 0;
79
+ white-space: nowrap;
80
+ }
81
+
82
+ .status-backend-ready .statusPill {
83
+ background: var(--c-cobalt-50);
84
+ color: var(--c-cobalt-700);
85
+ }
86
+
87
+ .status-stub .statusPill {
88
+ background: var(--c-orange-50, #fff4e5);
89
+ color: var(--c-orange-knvb);
90
+ }
91
+
92
+ .status-external .statusPill {
93
+ background: var(--c-cobalt-100);
94
+ color: var(--c-cobalt-900);
95
+ }
96
+
97
+ .status-built-in .statusPill {
98
+ background: var(--c-cobalt-50);
99
+ color: var(--c-cobalt-700);
100
+ }
101
+
102
+ .description {
103
+ font-size: 14px;
104
+ color: var(--c-cobalt-700);
105
+ margin: 0 0 var(--space-4);
106
+ line-height: 1.55;
107
+ }
108
+
109
+ .meta {
110
+ display: grid;
111
+ grid-template-columns: max-content 1fr;
112
+ gap: 6px var(--space-4);
113
+ margin: 0;
114
+ font-size: 13px;
115
+ }
116
+
117
+ .meta dt {
118
+ color: var(--c-cobalt-400);
119
+ font-weight: 500;
120
+ text-transform: uppercase;
121
+ letter-spacing: 0.06em;
122
+ font-size: 11px;
123
+ align-self: center;
124
+ }
125
+
126
+ .meta dd {
127
+ margin: 0;
128
+ color: var(--c-cobalt-900);
129
+ align-self: center;
130
+ }
131
+
132
+ .muted {
133
+ color: var(--c-cobalt-400);
134
+ font-style: italic;
135
+ }
136
+
137
+ /* Grid for the overview page. */
138
+ .grid {
139
+ display: grid;
140
+ gap: var(--space-5);
141
+ margin: var(--space-5) 0;
142
+ }
143
+
144
+ .grid-1 { grid-template-columns: 1fr; }
145
+ .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
146
+ .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
147
+ .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
148
+
149
+ @media (max-width: 768px) {
150
+ .grid-2, .grid-3, .grid-4 {
151
+ grid-template-columns: 1fr;
152
+ }
153
+ }
@@ -87,27 +87,27 @@
87
87
  }
88
88
 
89
89
  /* Tone palettes — set the .cardImage background. */
90
- .tone-mint .cardImage { background: var(--c-mint-100); }
90
+ .tone-mint .cardImage { background: var(--c-mint-300); }
91
91
  .tone-mint .cardEyebrow,
92
- .tone-mint .cardCta { color: var(--c-mint-700); }
92
+ .tone-mint .cardCta { color: var(--c-mint-500); }
93
93
 
94
- .tone-lavender .cardImage { background: var(--c-lavender-100); }
94
+ .tone-lavender .cardImage { background: var(--c-lavender-300); }
95
95
  .tone-lavender .cardEyebrow,
96
- .tone-lavender .cardCta { color: var(--c-lavender-700); }
96
+ .tone-lavender .cardCta { color: var(--c-lavender-500); }
97
97
 
98
- .tone-forest .cardImage { background: var(--c-forest-100); }
98
+ .tone-forest .cardImage { background: var(--c-forest-300); }
99
99
  .tone-forest .cardEyebrow,
100
- .tone-forest .cardCta { color: var(--c-forest-700); }
100
+ .tone-forest .cardCta { color: var(--c-forest-500); }
101
101
 
102
- .tone-terracotta .cardImage { background: var(--c-terracotta-100); }
102
+ .tone-terracotta .cardImage { background: var(--c-terracotta-300); }
103
103
  .tone-terracotta .cardEyebrow,
104
- .tone-terracotta .cardCta { color: var(--c-terracotta-700); }
104
+ .tone-terracotta .cardCta { color: var(--c-terracotta-500); }
105
105
 
106
- .tone-coral .cardImage { background: var(--c-coral-100); }
106
+ .tone-coral .cardImage { background: var(--c-coral-300); }
107
107
  .tone-coral .cardEyebrow,
108
- .tone-coral .cardCta { color: var(--c-coral-700); }
108
+ .tone-coral .cardCta { color: var(--c-coral-500); }
109
109
 
110
- .tone-workspace .cardImage { background: var(--c-workspace-100); }
110
+ .tone-workspace .cardImage { background: var(--c-workspace-300); }
111
111
  .tone-workspace .cardEyebrow,
112
112
  .tone-workspace .cardCta { color: var(--c-cobalt-700); }
113
113
 
@@ -57,13 +57,18 @@ export {default as FacetedFilters, FilterChip} from './FacetedFilters/FacetedFil
57
57
  export {default as CookieCli} from './CookieCli/CookieCli.jsx';
58
58
  export {default as GameModal} from './GameModal/GameModal.jsx';
59
59
 
60
- /* Diagram-set web-component React wrappers (cn-hex, cn-hex-prism,
61
- cn-platform, cn-domain-tree, cn-pipeline, cn-side-box, cn-honeycomb-bg,
62
- cn-pair, cn-arch-flow). Type-checked, autocompletable React surface
63
- for the framework-agnostic diagram set in @conduction/diagrams. The
64
- bare web components still work in plain HTML; the wrappers are the
65
- React-friendly version. */
66
- export {Hex, HexPrism, Platform, DomainTree, DiagramPipeline, SideBox, HoneycombBg, Pair, ArchFlow} from './Diagrams/Diagrams.jsx';
60
+ /* Diagram-set web-component React wrappers (cn-hex, cn-platform,
61
+ cn-domain-tree, cn-pipeline, cn-side-box, cn-honeycomb-bg, cn-pair,
62
+ cn-arch-flow). Type-checked, autocompletable React surface for the
63
+ framework-agnostic diagram set in @conduction/diagrams. Brand is
64
+ flat-hex only; the 3D prism wrapper was removed in v3.0.0. */
65
+ export {Hex, Platform, DomainTree, DiagramPipeline, SideBox, HoneycombBg, Pair, ArchFlow} from './Diagrams/Diagrams.jsx';
66
+
67
+ /* LeafCard — metadata header for an Open Register leaf integration.
68
+ <LeafGrid> renders a responsive grid of LeafCards for the overview
69
+ page; <LeafCard> on its own anchors the top of a per-leaf docs
70
+ page. See docs/Integrations/leaf-system.md for the worked use. */
71
+ export {default as LeafCard, LeafGrid} from './LeafCard/LeafCard.jsx';
67
72
  export {default as ComposeBlock} from './ComposeBlock/ComposeBlock.jsx';
68
73
  export {default as AppsGrid} from './AppsGrid/AppsGrid.jsx';
69
74
  export {default as AppMock} from './AppMock/AppMock.jsx';
@@ -38,97 +38,68 @@
38
38
  --c-cobalt-800: #102246;
39
39
  --c-cobalt-900: #0A172F;
40
40
 
41
- /* Pastel families for hex-prism categories (per visual-motifs.md)
42
- Each family has FIVE roles for prism construction:
43
- -50 ultra-light wash (ground / page bg accents)
44
- -100 top-face fill (the "lit" face you see in plan view)
45
- -300 left-face fill (the slightly shaded vertical face)
46
- -500 right-face / stroke (the deeper vertical face + outlines)
47
- -700 ink — text on prism, pill outline, chip text
48
-
49
- PRISM-FAMILY POLICY (locked 2026-04):
50
- Component prisms get ONE of: lavender, mint, forest, terracotta.
51
- The workspace prism uses workspace-blue (= Nextcloud's own brand blue).
52
- Cobalt is brand chrome, NOT a prism family.
41
+ /* Flat-hex category families. Two stops per family — the brand is
42
+ flat-hex only (the 3D prism mechanism was removed in v3.0.0), so
43
+ we no longer need separate -50/-100 face fills or -700 ink stops.
44
+
45
+ -300 lighter hover/wash variant
46
+ -500 saturated face the canonical fill for the category
47
+
48
+ HEX-FAMILY POLICY (locked 2026-04, trimmed 2026-05):
49
+ Component hexes pick exactly one of: lavender, mint, forest,
50
+ terracotta. The workspace hex uses workspace-blue (= Nextcloud's
51
+ own brand blue). Cobalt is brand chrome, NOT a category.
53
52
  "Kernel" is a banned word in the brand vocabulary (see
54
53
  identity/voice.html); use "workspace" everywhere.
55
- Coral, gold, gray are NOT prism families. They serve different jobs:
54
+ Coral, gold, gray are NOT category families. They serve specific jobs:
56
55
  · coral = KNVB-orange accent (focus, hover, single-use highlights). ≤ 8 % page area.
57
- · gold = "Conduction Certified" mark ONLY. Never on a generic prism.
56
+ · gold = "Conduction Certified" mark ONLY. Never on a generic hex.
58
57
  · gray = neutral surfaces / strokes. Not a category.
59
58
  */
60
59
 
61
60
  /* — Component family 1: lavender (process / workflow) — */
62
- --c-lavender-50: #F6F2FC;
63
- --c-lavender-100: #ECE6F8;
64
61
  --c-lavender-300: #B7A7E3;
65
62
  --c-lavender-500: #7E66C9;
66
- --c-lavender-700: #483982;
67
63
 
68
64
  /* — Component family 2: mint (integrate / connect) — */
69
- --c-mint-50: #EAF7F0;
70
- --c-mint-100: #DCF1E6;
71
65
  --c-mint-300: #87CFA8;
72
66
  --c-mint-500: #2E9866;
73
- --c-mint-700: #155234;
74
67
 
75
68
  /* — Component family 3: forest (data / trustworthy / NLDS-compliant)
76
- Distinct from mint — deeper, denser, more "official." Use
77
- this for prisms that handle data and registers. — */
78
- --c-forest-50: #EEF5EE;
79
- --c-forest-100: #D7E8D6;
69
+ Distinct from mint — deeper, denser, more "official." Use this
70
+ for hexes that handle data and registers. — */
80
71
  --c-forest-300: #7DAA7C;
81
72
  --c-forest-500: #3D7C3A;
82
- --c-forest-700: #1E461C;
83
73
 
84
74
  /* — Component family 4: terracotta (documents / human work)
85
- Tuned around the brand vermillion (#AE1C28) as its 700-deep,
86
- so it ties to the Dutch flag without the "alarm" of pure red. — */
87
- --c-terracotta-50: #FBF1EE;
88
- --c-terracotta-100: #F4DCD3;
75
+ Tuned around the brand vermillion (#AE1C28), so it ties to the
76
+ Dutch flag without the "alarm" of pure red. — */
89
77
  --c-terracotta-300: #DA9D8A;
90
78
  --c-terracotta-500: #B25E48;
91
- --c-terracotta-700: #6E2A1C;
92
79
 
93
80
  /* — Workspace family: workspace-blue (= Nextcloud's own brand blue tints) — */
94
- --c-workspaceblue-50: #E5F2FA;
95
- --c-workspaceblue-100: #C8E5F5;
96
81
  --c-workspaceblue-300: #67BEEA;
97
82
  --c-workspaceblue-500: #0082C9; /* Nextcloud blue */
98
- --c-workspaceblue-700: #014C77;
99
83
 
100
- /* ----- Reserved colors (NOT prism families) -----
84
+ /* ----- Reserved colors (NOT category families) -----
101
85
  Kept in tokens because they have specific jobs elsewhere. */
102
86
 
103
87
  /* Coral = KNVB orange accent only — focus rings, hover, occasional highlight. */
104
- --c-coral-50: #FFF3ED;
105
- --c-coral-100: #FFE4DA;
106
88
  --c-coral-300: #FAB29C;
107
89
  --c-coral-500: #F36C21; /* = KNVB */
108
- --c-coral-700: #9B3A0E;
109
90
 
110
91
  /* Gold = Conduction Certified mark ONLY. Reserved for the cert avatar
111
92
  and trustmark badges. Do not use as a generic family color. */
112
- --c-gold-50: #FDF8E8;
113
- --c-gold-100: #FBF1D5;
114
93
  --c-gold-300: #ECC668;
115
94
  --c-gold-500: #C99A1F;
116
- --c-gold-700: #765806;
117
95
 
118
96
  /* Gray = neutral surfaces, strokes, side-box chrome. Not a category. */
119
- --c-gray-50: #F4F5F8;
120
- --c-gray-100: #ECEEF2;
121
97
  --c-gray-300: #B7BDC9;
122
98
  --c-gray-500: #6B7280;
123
- --c-gray-700: #3A4150;
124
99
 
125
- /* Workspace family alias — points to workspace-blue (Nextcloud).
126
- The hex-prism API stays uniform: --c-workspace-{50,100,300,500,700} */
127
- --c-workspace-50: var(--c-workspaceblue-50);
128
- --c-workspace-100: var(--c-workspaceblue-100);
100
+ /* Workspace family alias — points to workspace-blue (Nextcloud). */
129
101
  --c-workspace-300: var(--c-workspaceblue-300);
130
102
  --c-workspace-500: var(--c-workspaceblue-500);
131
- --c-workspace-700: var(--c-workspaceblue-700);
132
103
 
133
104
  /* ---------- Semantic theme.conduction-2026 ---------- */
134
105
  /* Brand */
@@ -22,11 +22,10 @@ Every Conduction diagram follows the same brand rules: pointy-top hexes, fixed p
22
22
  | Component | Status | Purpose |
23
23
  | --- | --- | --- |
24
24
  | `<cn-hex>` | Available | Pointy-top hex primitive. Label + icon, nine colours, four sizes, solid or outline, optional interactive state. |
25
- | `<cn-hex-prism>` | Available | 3D isometric prism. Six families, four sizes, slots for label / icon / kicker / pills, coming-state badge. |
26
25
  | `<cn-domain-tree>` | Available | Vertical apex-and-branches layout for one-to-many domain maps. Slot-driven; multi-trunk diagrams stack two trees. |
27
- | `<cn-platform>` | Available | Workspace-plus-orbiting-apps cluster. Six neighbours in a hex ring around a central apex (typically a cobalt cn-hex-prism representing the Nextcloud workspace). |
26
+ | `<cn-platform>` | Available | Workspace-plus-orbiting-apps cluster. Six neighbours in a hex ring around a central cobalt cn-hex representing the Nextcloud workspace. |
28
27
  | `<cn-pipeline>` | Available | Horizontal flow of stages with auto-inserted arrow connectors. Three arrow tones. |
29
- | `<cn-side-box>` | Available | Rectangle-feed-prism pattern. Header chip + icon-and-label rows. Three widths, optional compact + footer. |
28
+ | `<cn-side-box>` | Available | Rectangle-feed-hex pattern. Header chip + icon-and-label rows. Three widths, optional compact + footer. |
30
29
  | `<cn-honeycomb-bg>` | Available | Honeycomb backdrop wrapper. Theme + accent + density attributes. Parallax in v2. |
31
30
 
32
31
  ## Usage
@@ -71,4 +70,4 @@ No build step needed. Drop the module into any HTML page:
71
70
 
72
71
  ## Roadmap
73
72
 
74
- See the planned components above. Built in this order: `cn-hex` ✅ → `cn-hex-prism` `cn-domain-tree` (first real consumer on the new identity/domains.html page) → `cn-platform` → `cn-pipeline` → `cn-side-box` → `cn-honeycomb-bg`.
73
+ Brand is flat-hex only. The 3D `<cn-hex-prism>` primitive was removed in v3.0.0 (`@conduction/docusaurus-preset` 3.0.0).
@@ -1,15 +1,15 @@
1
1
  /**
2
- * <cn-pipeline> — horizontal flow of prisms or hexes connected by arrows.
2
+ * <cn-pipeline> — horizontal flow of hexes connected by arrows.
3
3
  *
4
4
  * The flattened cousin of cn-platform. Used in solution pages, how-
5
5
  * it-works sections, and any sequence diagram where data moves
6
6
  * left-to-right through a series of stages.
7
7
  *
8
8
  * <cn-pipeline>
9
- * <cn-hex-prism family="coral">Source</cn-hex-prism>
10
- * <cn-hex-prism family="lavender">Process</cn-hex-prism>
11
- * <cn-hex-prism family="cobalt">Workspace</cn-hex-prism>
12
- * <cn-hex-prism family="mint">Sink</cn-hex-prism>
9
+ * <cn-hex color="lavender">Source</cn-hex>
10
+ * <cn-hex color="forest">Process</cn-hex>
11
+ * <cn-hex color="cobalt">Workspace</cn-hex>
12
+ * <cn-hex color="mint">Sink</cn-hex>
13
13
  * </cn-pipeline>
14
14
  *
15
15
  * The component reads its own light-DOM children, assigns each to a
@@ -2,11 +2,11 @@
2
2
  * <cn-platform> — workspace-plus-orbiting-apps cluster.
3
3
  *
4
4
  * The canonical "what is ConNext" diagram: a Nextcloud workspace at
5
- * the centre, six application prisms arranged in a hex ring around
6
- * it. Used on landing pages, product overviews, ecosystem visuals.
5
+ * the centre, six application hexes arranged in a hex ring around it.
6
+ * Used on landing pages, product overviews, ecosystem visuals.
7
7
  *
8
8
  * Slots
9
- * apex — central element; required (typically a cobalt cn-hex-prism).
9
+ * apex — central element; required (typically a cobalt cn-hex).
10
10
  * Same slot name as cn-domain-tree; "kernel" is a banned
11
11
  * word in the brand vocabulary, see identity/voice.html.
12
12
  * default — orbiting apps; up to six, positioned in this order:
@@ -19,8 +19,8 @@
19
19
  * Background of the surrounding stage.
20
20
  *
21
21
  * The component owns only layout + ground + optional connector ring.
22
- * Each child element keeps its own styling, so the apex element can
23
- * be a hex prism or a flat hex interchangeably.
22
+ * Each child element keeps its own styling. Brand is flat-hex only;
23
+ * the 3D prism was removed in v3.0.0.
24
24
  */
25
25
 
26
26
  class CnPlatform extends HTMLElement {
@@ -1,7 +1,7 @@
1
1
  /**
2
- * <cn-side-box> — the rectangle-feed-prism pattern.
2
+ * <cn-side-box> — the rectangle-feed-hex pattern.
3
3
  *
4
- * Hex prisms are "the system". Side-boxes are "what feeds it" or
4
+ * Hexes are "the system". Side-boxes are "what feeds it" or
5
5
  * "what consumes it". The shape difference is the hierarchy.
6
6
  *
7
7
  * <cn-side-box header="YOUR DATA">
@@ -7,22 +7,19 @@
7
7
  * Usage (no build step):
8
8
  * <script type="module" src="../diagrams/src/index.js"></script>
9
9
  * <cn-hex color="cobalt" size="lg">Connect</cn-hex>
10
- * <cn-hex-prism family="coral" size="lg">Catalogi</cn-hex-prism>
11
10
  *
12
11
  * Components:
13
12
  * <cn-hex> — pointy-top hex primitive (label + icon)
14
- * <cn-hex-prism> — 3D isometric prism, the atomic unit for platform diagrams
15
13
  * <cn-domain-tree> — vertical apex-and-branches layout for domain maps
16
14
  * <cn-platform> — workspace-plus-orbiting-apps cluster
17
15
  * <cn-pipeline> — horizontal flow of stages connected by arrows
18
- * <cn-side-box> — rectangle-feed-prism pattern for non-app surfaces
16
+ * <cn-side-box> — rectangle-feed pattern for non-app surfaces
19
17
  * <cn-honeycomb-bg> — honeycomb backdrop wrapper for hero scenes
20
18
  * <cn-pair> — two systems bridged by an orange arrow
21
19
  * <cn-arch-flow> — single row of an architecture / request-flow diagram
22
20
  */
23
21
 
24
22
  export * from './cn-hex.js';
25
- export * from './cn-hex-prism.js';
26
23
  export * from './cn-domain-tree.js';
27
24
  export * from './cn-platform.js';
28
25
  export * from './cn-pipeline.js';
@@ -1,163 +0,0 @@
1
- /**
2
- * <cn-hex-prism> — the 3D isometric prism primitive.
3
- *
4
- * The atomic unit for ConNext platform diagrams. A pointy-top hexagon
5
- * extruded ~30° in isometric view, three faces tinted from one family
6
- * palette: top = family-100 (lit), left = family-300, right = family-500,
7
- * ink = family-700. Six families ship: cobalt (workspace only), coral,
8
- * lavender, gold, mint, gray.
9
- *
10
- * Slots
11
- * default — label text (the prism's name)
12
- * icon — icon SVG / image, sits above the label on the top face
13
- * kicker — small uppercase line under the label (e.g. "DATA · STABLE")
14
- * pills — optional pill stack floating on the top face
15
- *
16
- * Attributes
17
- * family cobalt | coral | lavender | gold | mint | gray (default: coral)
18
- * size sm | md | lg | xl or any CSS length (default: md = 144px)
19
- * state coming (optional)
20
- *
21
- * Geometry: SVG viewBox 240×252, paths inscribed for a pointy-top hex
22
- * extruded by R*0.45 (depth vector). All three faces drawn as polygons,
23
- * face edges drawn as 1.25-stroke polylines at 18% opacity for subtle
24
- * faceting. The label-content layer sits in the upper portion so the
25
- * text hits the top face only, not the side faces.
26
- */
27
-
28
- const SIZES = { sm: 96, md: 144, lg: 192, xl: 240 };
29
-
30
- const FAMILIES = {
31
- cobalt: { top: 'var(--c-cobalt-100)', left: 'var(--c-cobalt-400)', right: 'var(--c-cobalt-700)', ink: '#fff' },
32
- coral: { top: 'var(--c-coral-100)', left: 'var(--c-coral-300)', right: 'var(--c-coral-500)', ink: 'var(--c-coral-700)' },
33
- lavender: { top: 'var(--c-lavender-100)', left: 'var(--c-lavender-300)', right: 'var(--c-lavender-500)', ink: 'var(--c-lavender-700)' },
34
- gold: { top: 'var(--c-gold-100)', left: 'var(--c-gold-300)', right: 'var(--c-gold-500)', ink: 'var(--c-gold-700)' },
35
- mint: { top: 'var(--c-mint-100)', left: 'var(--c-mint-300)', right: 'var(--c-mint-500)', ink: 'var(--c-mint-700)' },
36
- gray: { top: 'var(--c-gray-100)', left: 'var(--c-gray-300)', right: 'var(--c-gray-500)', ink: 'var(--c-gray-700)' },
37
- };
38
-
39
- class CnHexPrism extends HTMLElement {
40
- static get observedAttributes() {
41
- return ['family', 'size', 'state'];
42
- }
43
-
44
- constructor() {
45
- super();
46
- this.attachShadow({ mode: 'open' });
47
- }
48
-
49
- connectedCallback() { this.render(); }
50
- attributeChangedCallback() { if (this.shadowRoot) this.render(); }
51
-
52
- render() {
53
- const familyKey = this.getAttribute('family') || 'coral';
54
- const sizeAttr = this.getAttribute('size') || 'md';
55
- const state = this.getAttribute('state');
56
-
57
- const f = FAMILIES[familyKey] || FAMILIES.coral;
58
- const sizePx = SIZES[sizeAttr] ? `${SIZES[sizeAttr]}px` : sizeAttr;
59
-
60
- this.shadowRoot.innerHTML = `
61
- <style>
62
- :host {
63
- --face-top: ${f.top};
64
- --face-left: ${f.left};
65
- --face-right: ${f.right};
66
- --ink: ${f.ink};
67
-
68
- display: inline-block;
69
- width: ${sizePx};
70
- position: relative;
71
- font-family: var(--conduction-typography-font-family-body, system-ui, sans-serif);
72
- color: var(--ink);
73
- }
74
-
75
- svg.shape { display: block; width: 100%; height: auto; overflow: visible; }
76
- svg.shape .face-top { fill: var(--face-top); }
77
- svg.shape .face-left { fill: var(--face-left); }
78
- svg.shape .face-right { fill: var(--face-right); }
79
- svg.shape .face-edge { stroke: var(--ink); stroke-width: 1.25; fill: none; opacity: 0.18; }
80
-
81
- .content {
82
- position: absolute;
83
- inset: 0;
84
- display: flex; flex-direction: column;
85
- align-items: center; justify-content: center;
86
- padding-bottom: 18%; /* push content onto top face only */
87
- color: var(--ink);
88
- text-align: center;
89
- pointer-events: none;
90
- }
91
- ::slotted([slot="icon"]) {
92
- width: 22%;
93
- height: auto;
94
- margin-bottom: 4%;
95
- color: currentColor;
96
- fill: currentColor;
97
- }
98
- .label {
99
- font-size: calc(${sizePx} * 0.10);
100
- font-weight: 700;
101
- letter-spacing: -0.01em;
102
- line-height: 1.15;
103
- }
104
- ::slotted([slot="kicker"]) {
105
- font-family: var(--conduction-typography-font-family-code, ui-monospace, monospace);
106
- font-size: calc(${sizePx} * 0.066);
107
- letter-spacing: 0.12em;
108
- text-transform: uppercase;
109
- margin-top: 2%;
110
- opacity: 0.78;
111
- color: currentColor;
112
- }
113
- ::slotted([slot="pills"]) {
114
- display: flex; flex-direction: column;
115
- gap: 4px; margin-top: 4%;
116
- align-items: center;
117
- }
118
-
119
- ${state === 'coming' ? `
120
- .badge {
121
- position: absolute;
122
- top: 12%; right: 6%;
123
- background: var(--c-cobalt-700);
124
- color: white;
125
- font-family: var(--conduction-typography-font-family-code, ui-monospace, monospace);
126
- font-size: calc(${sizePx} * 0.05);
127
- font-weight: 700;
128
- letter-spacing: 0.08em;
129
- text-transform: uppercase;
130
- padding: 3px 7px;
131
- border-radius: 999px;
132
- pointer-events: none;
133
- }
134
- ` : ''}
135
- </style>
136
-
137
- <svg class="shape" viewBox="0 0 240 252" aria-hidden="true">
138
- <!-- left face -->
139
- <polygon class="face-left" points="120,84 60,118 60,212 120,246"/>
140
- <!-- right face -->
141
- <polygon class="face-right" points="120,84 180,118 180,212 120,246"/>
142
- <!-- top face (drawn last so it sits on top of the side faces at the seam) -->
143
- <polygon class="face-top" points="120,6 180,40 180,118 120,152 60,118 60,40"/>
144
- <!-- subtle face edges, point down + center vertical -->
145
- <polyline class="face-edge" points="120,84 60,118 120,152 180,118 120,84"/>
146
- <polyline class="face-edge" points="120,152 120,246"/>
147
- </svg>
148
- <div class="content">
149
- <slot name="icon"></slot>
150
- <span class="label"><slot></slot></span>
151
- <slot name="kicker"></slot>
152
- <slot name="pills"></slot>
153
- </div>
154
- ${state === 'coming' ? `<div class="badge">Coming</div>` : ''}
155
- `;
156
- }
157
- }
158
-
159
- if (!customElements.get('cn-hex-prism')) {
160
- customElements.define('cn-hex-prism', CnHexPrism);
161
- }
162
-
163
- export { CnHexPrism };