@conduction/docusaurus-preset 2.4.2 → 2.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conduction/docusaurus-preset",
3
- "version": "2.4.2",
3
+ "version": "2.6.0",
4
4
  "scripts": {
5
5
  "prepack": "node scripts/prepack-bundle-css.js"
6
6
  },
@@ -0,0 +1,319 @@
1
+ /**
2
+ * <AtomZones />
3
+ *
4
+ * The "Five atoms, one chassis" visual reference. Renders five
5
+ * zone cards, each focusing on one atom of the canonical Conduction
6
+ * app chassis: Topbar, Left navigation, Main column, Page header,
7
+ * Sidebar. The focused atom is outlined in KNVB orange; everything
8
+ * else fades to 25% opacity so the reader sees *where* the atom
9
+ * sits in context.
10
+ *
11
+ * Mirrors the static-HTML reference at
12
+ * preview/components/app-mock.html#five-atoms
13
+ * so the React surface and the design-system kit page stay aligned.
14
+ *
15
+ * Used by Docusaurus consumers (nextcloud-vue.conduction.nl,
16
+ * procest.conduction.nl, openregister.conduction.nl) to teach the
17
+ * chassis-plus-atoms pattern on architecture pages.
18
+ *
19
+ * Self-contained: bundles its own chassis JSX + zone-focus styles
20
+ * via :global() in AtomZones.module.css. Doesn't reuse <AppMock/>'s
21
+ * variants — those intentionally skip the .pageHeader atom — so
22
+ * the page-header zone can render correctly.
23
+ *
24
+ * No props today. A future `app="..."` prop could re-tint the body
25
+ * accent (cobalt/mint/lavender), but the zone-focus story is
26
+ * inherently chassis-level, not variant-level.
27
+ */
28
+
29
+ import React from 'react';
30
+ import styles from './AtomZones.module.css';
31
+
32
+ const ZONES = [
33
+ {
34
+ code: '.topbar',
35
+ title: 'Topbar',
36
+ applies: <><strong>App</strong> &middot; <strong>Desk</strong> &middot; always</>,
37
+ body:
38
+ "The Nextcloud chrome row. Sits across every page unconditionally because every Conduction app lives inside Nextcloud's workspace. The shelf icons are the cross-app navigation; per-app links never go here.",
39
+ focus: 'focusTopbar',
40
+ facts: [
41
+ ['Inside', <>logo, 14 app-shelf icons, spacer, optional pill, bell, avatar</>],
42
+ ['Tokens', <><code>--c-blue-cobalt</code> bg; whites at <code>0.4</code> / <code>0.7</code> / <code>1.0</code> alpha</>],
43
+ ['Height', <><code>24px</code> fixed; <code>flex-shrink: 0</code></>],
44
+ ],
45
+ tips: [
46
+ { text: "The shelf shows other Nextcloud apps, never this app's own pages" },
47
+ { text: 'Avatar is the only solid white circle, top-right' },
48
+ { text: "Don't add a per-app logo here; the body handles that", dont: true },
49
+ ],
50
+ },
51
+ {
52
+ code: '.nav',
53
+ title: 'Left navigation',
54
+ applies: <><strong>App</strong> &middot; required &middot; <em className={styles.never}>Desk: never</em></>,
55
+ body:
56
+ "The per-app sidebar. Carries this app's own primary navigation, plus a footer pinned to the bottom for global access (Settings, Feedback). The active item is the only place cobalt-100 backgrounds a row.",
57
+ focus: 'focusNav',
58
+ facts: [
59
+ ['Inside', <>navHead (cobalt-blue card with hex glyph + label), 5&ndash;9 nav items (one with <code>.active</code>), and a <code>.footer</code> with Settings + Feedback pinned to the bottom</>],
60
+ ['Width', <><code>22%</code>, min <code>100px</code>; <code>flex-shrink: 0</code></>],
61
+ ['Tokens', <><code>--c-cobalt-50</code> bg; <code>--c-cobalt-100</code> right border + active bg + footer divider; <code>--c-orange-knvb</code> on the navHead hex</>],
62
+ ],
63
+ tips: [
64
+ { text: 'Always exactly one .active item; never zero, never two' },
65
+ { text: 'Footer always carries Settings + Feedback, anchored bottom via margin-top: auto' },
66
+ { text: "Don't add per-app sign-out here; the user's avatar in the topbar handles identity", dont: true },
67
+ ],
68
+ },
69
+ {
70
+ code: '.col',
71
+ title: 'Main column',
72
+ applies: <><strong>App</strong> &middot; <strong>Desk</strong> &middot; always</>,
73
+ body:
74
+ 'The work surface. In an App pattern, the column opens with a .pageHeader (title + actions), then KPI strip and panels. In a Desk pattern, .col nests inside .grid to become a full-bleed widget canvas with no page header.',
75
+ focus: 'focusCol',
76
+ facts: [
77
+ ['Inside', <>App pattern: <code>.pageHeader</code> + <code>.kpiRow</code> + <code>.panelRow</code>s + tables. Desk pattern: <code>.grid</code> with <code>.w</code> widgets (no pageHeader)</>],
78
+ ['Width', <><code>flex: 1</code>; <code>min-width: 0</code>; <code>overflow: hidden</code></>],
79
+ ['Tokens', <>White bg; tokens scope to inner panels (<code>--c-cobalt-100</code> borders, <code>--c-mint-500</code> / <code>--c-orange-knvb</code> KPI accents)</>],
80
+ ],
81
+ tips: [
82
+ { text: 'The single orange accent of the variant lives somewhere in here, never in the rails' },
83
+ { text: "KPI strip is the most-recognisable App-pattern signature; use it when there's a number worth surfacing" },
84
+ { text: "Don't let panels overflow horizontally; min-width: 0 is load-bearing", dont: true },
85
+ ],
86
+ },
87
+ {
88
+ code: '.pageHeader',
89
+ title: 'Page header',
90
+ applies: <><strong>Index</strong> &middot; <strong>Detail</strong> &middot; <em className={styles.never}>Desk: never</em></>,
91
+ body:
92
+ "The first row of .col on every Index and Detail template. Carries the page title (left) and exactly two action buttons (right): one ghost (border-only, secondary action) and one primary (filled cobalt). The header tracks .col's width: when the sidebar is open the header constrains; when the sidebar is closed it spans full-width.",
93
+ focus: 'focusPageHeader',
94
+ facts: [
95
+ ['Inside', <>title-bar (left, cobalt-blue rounded rect with the page title), spacer, then exactly two action buttons: <code>.btn.ghost</code> (white with cobalt border, secondary) on the left of the pair, then <code>.btn</code> (filled cobalt, primary)</>],
96
+ ['Height', <><code>14&ndash;16px</code> band, sits flush with <code>.col</code>'s top padding</>],
97
+ ['Width', <>tracks <code>.col</code>: full-spread when sidebar closed, constrained when sidebar open</>],
98
+ ['Tokens', <><code>--c-blue-cobalt</code> for the title-bar and primary button; <code>--c-cobalt-200</code> border on ghost button; white bg on ghost</>],
99
+ ],
100
+ tips: [
101
+ { text: 'Identical anatomy on Index and Detail; only the title changes' },
102
+ { text: 'Exactly two buttons, never one, never three. If you need a third action, group into an "Actions…" dropdown behind the ghost button' },
103
+ { text: "Don't render the page title as plain text inside a panel; the page header IS the title", dont: true },
104
+ ],
105
+ },
106
+ {
107
+ code: '.detail',
108
+ title: 'Sidebar',
109
+ applies: <><strong>App</strong> &middot; optional &middot; <em className={styles.never}>Desk: never</em></>,
110
+ body:
111
+ 'The right-hand sidebar. Optional, dismissible, anchored to the active record or the active view. Carries an icon + title + description in a header, then a tabbed body (Search / Columns by default). Class stays .detail for code; we call it the Sidebar in copy.',
112
+ focus: 'focusDetail',
113
+ facts: [
114
+ ['Inside', <><code>.sb-head</code> (icon + title + description + close), <code>.sb-tabs</code> (2&ndash;3 tabs, one <code>.active</code>), then a <code>.sb-body</code> of inputs / filters / pinned metadata</>],
115
+ ['Width', <><code>26%</code>, min <code>130px</code>; <code>flex-shrink: 0</code></>],
116
+ ['Tokens', <>White bg; <code>--c-cobalt-100</code> left border; <code>--c-blue-cobalt</code> active-tab underline; <code>--c-cobalt-50</code> on the icon background</>],
117
+ ],
118
+ tips: [
119
+ { text: "Sidebar should be dismissible; it's a drawer, not a permanent rail" },
120
+ { text: 'Default tabs on an Index page: Search + Columns. Default on Detail: Overview + Activity' },
121
+ { text: "Don't put global navigation here; that's .nav's job. The sidebar is scoped to the current view.", dont: true },
122
+ ],
123
+ },
124
+ ];
125
+
126
+ /**
127
+ * Reference chassis with all five atoms: topbar, nav (with footer),
128
+ * col (with pageHeader + kpiRow + panelRow), and detail.rich.
129
+ *
130
+ * Class names are emitted as global strings so the chassis renders
131
+ * with the same selectors used in the design-system kit page; the
132
+ * AtomZones.module.css uses :global(...) to target them. This means
133
+ * one source of styling for the chassis, regardless of whether it's
134
+ * loaded inside a CSS-Modules pipeline (preset consumers) or via the
135
+ * static kit page.
136
+ */
137
+ function ChassisFrame({ focus }) {
138
+ return (
139
+ <div className={`${styles.zoneFrame} ${styles[focus]}`}>
140
+ <div className="am-frame">
141
+ <div className="am-topbar">
142
+ <div className="am-logo"></div>
143
+ {Array.from({ length: 14 }).map((_, i) => (
144
+ <div key={i} className="am-icon"></div>
145
+ ))}
146
+ <div className="am-spacer"></div>
147
+ <div className="am-bell"></div>
148
+ <div className="am-avatar"></div>
149
+ </div>
150
+ <div className="am-body">
151
+ <div className="am-nav">
152
+ <div className="am-navHead">
153
+ <div className="am-h"></div>
154
+ <div className="am-l"></div>
155
+ </div>
156
+ {[true, false, false, false, false].map((active, i) => (
157
+ <div
158
+ key={i}
159
+ className={`am-item ${active ? 'am-active' : ''}`}
160
+ >
161
+ <div className="am-ico"></div>
162
+ <div className="am-l"></div>
163
+ </div>
164
+ ))}
165
+ <div className="am-footer">
166
+ <div className="am-item">
167
+ <div className="am-ico"></div>
168
+ <div className="am-l"></div>
169
+ </div>
170
+ <div className="am-item">
171
+ <div className="am-ico"></div>
172
+ <div className="am-l"></div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ <div className="am-col">
177
+ <div className="am-pageHeader">
178
+ <div className="am-title-bar"></div>
179
+ <div className="am-spacer"></div>
180
+ <div className="am-actions">
181
+ <div className="am-btn am-ghost"></div>
182
+ <div className="am-btn"></div>
183
+ </div>
184
+ </div>
185
+ <div className="am-kpiRow">
186
+ <div className="am-kpi">
187
+ <div className="am-ico"></div>
188
+ <div className="am-meta">
189
+ <div className="am-num"></div>
190
+ <div className="am-label"></div>
191
+ </div>
192
+ </div>
193
+ <div className="am-kpi am-forest">
194
+ <div className="am-ico"></div>
195
+ <div className="am-meta">
196
+ <div className="am-num"></div>
197
+ <div className="am-label"></div>
198
+ </div>
199
+ </div>
200
+ <div className="am-kpi am-amber">
201
+ <div className="am-ico"></div>
202
+ <div className="am-meta">
203
+ <div className="am-num"></div>
204
+ <div className="am-label"></div>
205
+ </div>
206
+ </div>
207
+ </div>
208
+ <div className="am-panelRow">
209
+ <div className="am-panel">
210
+ <div className="am-head">
211
+ <div className="am-title"></div>
212
+ </div>
213
+ <div className="am-stack">
214
+ <div className="am-item">
215
+ <div className="am-lines">
216
+ <div className="am-l1"></div>
217
+ </div>
218
+ </div>
219
+ <div className="am-item">
220
+ <div className="am-lines">
221
+ <div className="am-l1"></div>
222
+ </div>
223
+ </div>
224
+ </div>
225
+ </div>
226
+ <div className="am-panel">
227
+ <div className="am-head">
228
+ <div className="am-title"></div>
229
+ </div>
230
+ <div className="am-stack">
231
+ <div className="am-item">
232
+ <div className="am-av am-b"></div>
233
+ <div className="am-lines">
234
+ <div className="am-l1"></div>
235
+ </div>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </div>
241
+ <div className="am-detail am-rich">
242
+ <div className="am-sb-head">
243
+ <div className="am-ico"></div>
244
+ <div className="am-meta">
245
+ <div className="am-title"></div>
246
+ <div className="am-desc"></div>
247
+ </div>
248
+ <div className="am-close"></div>
249
+ </div>
250
+ <div className="am-sb-tabs">
251
+ <div className="am-sb-tab am-active">
252
+ <div className="am-ico"></div>
253
+ <div className="am-l"></div>
254
+ </div>
255
+ <div className="am-sb-tab">
256
+ <div className="am-ico"></div>
257
+ <div className="am-l"></div>
258
+ </div>
259
+ </div>
260
+ <div className="am-sb-body">
261
+ <div className="am-sb-input"></div>
262
+ <div className="am-sb-filter">
263
+ <div className="am-lbl"></div>
264
+ <div className="am-field"></div>
265
+ </div>
266
+ <div className="am-sb-filter">
267
+ <div className="am-lbl"></div>
268
+ <div className="am-field"></div>
269
+ </div>
270
+ <div className="am-sb-filter">
271
+ <div className="am-lbl"></div>
272
+ <div className="am-field"></div>
273
+ </div>
274
+ </div>
275
+ </div>
276
+ </div>
277
+ </div>
278
+ </div>
279
+ );
280
+ }
281
+
282
+ function ZoneCard({ zone }) {
283
+ return (
284
+ <div className={styles.zoneCard}>
285
+ <div className={styles.zoneHead}>
286
+ <code>{zone.code}</code>
287
+ <h3>{zone.title}</h3>
288
+ <span className={styles.applies}>{zone.applies}</span>
289
+ </div>
290
+ <p className={styles.lede}>{zone.body}</p>
291
+ <ChassisFrame focus={zone.focus} />
292
+ <dl className={styles.facts}>
293
+ {zone.facts.map(([term, def], i) => (
294
+ <React.Fragment key={i}>
295
+ <dt>{term}</dt>
296
+ <dd>{def}</dd>
297
+ </React.Fragment>
298
+ ))}
299
+ </dl>
300
+ <ul className={styles.tips}>
301
+ {zone.tips.map((tip, i) => (
302
+ <li key={i} className={tip.dont ? styles.dont : undefined}>
303
+ {tip.text}
304
+ </li>
305
+ ))}
306
+ </ul>
307
+ </div>
308
+ );
309
+ }
310
+
311
+ export default function AtomZones() {
312
+ return (
313
+ <div className={styles.zones}>
314
+ {ZONES.map((zone) => (
315
+ <ZoneCard key={zone.code} zone={zone} />
316
+ ))}
317
+ </div>
318
+ );
319
+ }
@@ -0,0 +1,713 @@
1
+ /**
2
+ * <AtomZones /> styles.
3
+ *
4
+ * Two layers:
5
+ *
6
+ * 1. Locally-scoped layout (zones grid, zone-card, zone-head,
7
+ * facts dl, tips list). Standard CSS-Modules class names.
8
+ *
9
+ * 2. The chassis atom toolkit (.am-frame, .am-topbar, .am-nav,
10
+ * .am-col, .am-pageHeader, .am-detail, etc.) declared via
11
+ * :global() so every chassis renders identically regardless of
12
+ * consumer Webpack config. Class names are `am-`-prefixed to
13
+ * avoid colliding with Docusaurus host-page utility classes.
14
+ *
15
+ * Mirrors the static-HTML reference at
16
+ * preview/components/app-mock.html#five-atoms
17
+ * (the .anatomy .zones / .zone-card / .zone-focus rules and the
18
+ * inline .frame .pageHeader / .frame .nav .footer additions).
19
+ *
20
+ * Tokens only; one orange accent (KNVB) reserved for the focused
21
+ * atom outline + the navHead hex glyph.
22
+ */
23
+
24
+ /* ============================================================
25
+ Layout — zones grid + zone-card
26
+ ============================================================ */
27
+
28
+ .zones {
29
+ display: grid;
30
+ grid-template-columns: 1fr 1fr;
31
+ gap: var(--space-5);
32
+ margin: var(--space-6) 0 var(--space-10);
33
+ }
34
+
35
+ @media (max-width: 1100px) {
36
+ .zones {
37
+ grid-template-columns: 1fr;
38
+ }
39
+ }
40
+
41
+ .zoneCard {
42
+ background: white;
43
+ border: 1px solid var(--c-cobalt-100);
44
+ border-radius: var(--radius-lg);
45
+ padding: var(--space-6);
46
+ display: flex;
47
+ flex-direction: column;
48
+ gap: var(--space-4);
49
+ }
50
+
51
+ .zoneHead {
52
+ display: flex;
53
+ align-items: baseline;
54
+ gap: var(--space-3);
55
+ flex-wrap: wrap;
56
+ }
57
+
58
+ .zoneHead code {
59
+ font-family: var(--conduction-typography-font-family-code);
60
+ font-size: 13px;
61
+ font-weight: 500;
62
+ color: var(--c-blue-cobalt);
63
+ background: var(--c-cobalt-50);
64
+ padding: 2px 8px;
65
+ border-radius: 3px;
66
+ }
67
+
68
+ .zoneHead h3 {
69
+ margin: 0;
70
+ font-size: 22px;
71
+ font-weight: 600;
72
+ color: var(--c-blue-cobalt);
73
+ letter-spacing: -0.01em;
74
+ }
75
+
76
+ .applies {
77
+ font-family: var(--conduction-typography-font-family-code);
78
+ font-size: 10px;
79
+ letter-spacing: 0.06em;
80
+ text-transform: uppercase;
81
+ color: var(--c-cobalt-400);
82
+ margin-left: auto;
83
+ }
84
+
85
+ .applies strong {
86
+ color: var(--c-mint-500);
87
+ font-weight: 500;
88
+ }
89
+
90
+ .never {
91
+ color: var(--c-cobalt-300);
92
+ font-style: italic;
93
+ }
94
+
95
+ .lede {
96
+ margin: 0;
97
+ color: var(--c-cobalt-700);
98
+ font-size: 14px;
99
+ line-height: 1.55;
100
+ }
101
+
102
+ .facts {
103
+ margin: 0;
104
+ display: grid;
105
+ grid-template-columns: 110px 1fr;
106
+ gap: 8px var(--space-4);
107
+ font-size: 13px;
108
+ line-height: 1.5;
109
+ }
110
+
111
+ .facts dt {
112
+ font-family: var(--conduction-typography-font-family-code);
113
+ font-size: 11px;
114
+ letter-spacing: 0.06em;
115
+ text-transform: uppercase;
116
+ color: var(--c-cobalt-400);
117
+ align-self: start;
118
+ padding-top: 2px;
119
+ }
120
+
121
+ .facts dd {
122
+ margin: 0;
123
+ color: var(--c-cobalt-700);
124
+ }
125
+
126
+ .facts dd code {
127
+ font-family: var(--conduction-typography-font-family-code);
128
+ font-size: 12px;
129
+ color: var(--c-blue-cobalt);
130
+ background: var(--c-cobalt-50);
131
+ padding: 1px 5px;
132
+ border-radius: 3px;
133
+ white-space: nowrap;
134
+ }
135
+
136
+ .tips {
137
+ list-style: none;
138
+ margin: 0;
139
+ padding: 0;
140
+ display: flex;
141
+ flex-direction: column;
142
+ gap: 6px;
143
+ }
144
+
145
+ .tips li {
146
+ font-size: 13px;
147
+ line-height: 1.5;
148
+ color: var(--c-cobalt-700);
149
+ padding-left: 18px;
150
+ position: relative;
151
+ }
152
+
153
+ .tips li::before {
154
+ content: '';
155
+ position: absolute;
156
+ left: 0;
157
+ top: 7px;
158
+ width: 8px;
159
+ height: 9px;
160
+ clip-path: var(--hex-pointy-top);
161
+ background: var(--c-orange-knvb);
162
+ }
163
+
164
+ .tips li.dont::before {
165
+ background: var(--c-red-vermillion, #c0392b);
166
+ }
167
+
168
+ /* ============================================================
169
+ Zone frame (the cobalt-50 cushion that holds the chassis)
170
+ ============================================================ */
171
+
172
+ .zoneFrame {
173
+ background: var(--c-cobalt-50);
174
+ border-radius: var(--radius-md);
175
+ padding: var(--space-4);
176
+ }
177
+
178
+ /* ============================================================
179
+ Chassis — global so the markup matches the design-system kit
180
+ ============================================================ */
181
+
182
+ .zoneFrame :global(.am-frame) {
183
+ width: 100%;
184
+ max-width: 560px;
185
+ margin: 0 auto;
186
+ aspect-ratio: 16 / 10;
187
+ background: white;
188
+ border: 1px solid var(--c-cobalt-100);
189
+ border-radius: var(--radius-lg);
190
+ box-shadow: var(--shadow-1);
191
+ overflow: hidden;
192
+ display: flex;
193
+ flex-direction: column;
194
+ font-family: var(--conduction-typography-font-family-body);
195
+ position: relative;
196
+ }
197
+
198
+ /* --- Topbar ---------------------------------------------------- */
199
+
200
+ .zoneFrame :global(.am-topbar) {
201
+ display: flex;
202
+ align-items: center;
203
+ gap: 4px;
204
+ padding: 6px 10px;
205
+ background: var(--c-blue-cobalt);
206
+ flex-shrink: 0;
207
+ height: 24px;
208
+ }
209
+
210
+ .zoneFrame :global(.am-topbar .am-logo) {
211
+ width: 16px;
212
+ height: 12px;
213
+ border-radius: 6px;
214
+ background: white;
215
+ }
216
+
217
+ .zoneFrame :global(.am-topbar .am-icon) {
218
+ width: 8px;
219
+ height: 8px;
220
+ border-radius: 1px;
221
+ background: rgba(255, 255, 255, 0.7);
222
+ }
223
+
224
+ .zoneFrame :global(.am-topbar .am-spacer) {
225
+ flex: 1;
226
+ }
227
+
228
+ .zoneFrame :global(.am-topbar .am-bell) {
229
+ width: 8px;
230
+ height: 8px;
231
+ border-radius: 50%;
232
+ background: rgba(255, 255, 255, 0.7);
233
+ }
234
+
235
+ .zoneFrame :global(.am-topbar .am-avatar) {
236
+ width: 10px;
237
+ height: 10px;
238
+ border-radius: 50%;
239
+ background: white;
240
+ }
241
+
242
+ /* --- Body wrapper --------------------------------------------- */
243
+
244
+ .zoneFrame :global(.am-body) {
245
+ flex: 1;
246
+ display: flex;
247
+ min-height: 0;
248
+ min-width: 0;
249
+ overflow: hidden;
250
+ }
251
+
252
+ /* --- Left navigation ----------------------------------------- */
253
+
254
+ .zoneFrame :global(.am-nav) {
255
+ width: 22%;
256
+ min-width: 100px;
257
+ flex-shrink: 0;
258
+ background: var(--c-cobalt-50);
259
+ border-right: 1px solid var(--c-cobalt-100);
260
+ padding: 8px;
261
+ display: flex;
262
+ flex-direction: column;
263
+ gap: 5px;
264
+ }
265
+
266
+ .zoneFrame :global(.am-nav .am-navHead) {
267
+ display: flex;
268
+ align-items: center;
269
+ gap: 6px;
270
+ background: var(--c-blue-cobalt);
271
+ padding: 6px;
272
+ border-radius: 4px;
273
+ margin-bottom: 4px;
274
+ }
275
+
276
+ .zoneFrame :global(.am-nav .am-navHead .am-h) {
277
+ width: 8px;
278
+ height: 9px;
279
+ clip-path: var(--hex-pointy-top);
280
+ background: var(--c-orange-knvb);
281
+ }
282
+
283
+ .zoneFrame :global(.am-nav .am-navHead .am-l) {
284
+ flex: 1;
285
+ height: 4px;
286
+ background: rgba(255, 255, 255, 0.7);
287
+ border-radius: 1px;
288
+ }
289
+
290
+ .zoneFrame :global(.am-nav .am-item) {
291
+ display: flex;
292
+ align-items: center;
293
+ gap: 6px;
294
+ padding: 4px 6px;
295
+ border-radius: 3px;
296
+ }
297
+
298
+ .zoneFrame :global(.am-nav .am-item.am-active) {
299
+ background: var(--c-cobalt-100);
300
+ }
301
+
302
+ .zoneFrame :global(.am-nav .am-item .am-ico) {
303
+ width: 8px;
304
+ height: 8px;
305
+ border-radius: 1px;
306
+ background: var(--c-cobalt-400);
307
+ flex-shrink: 0;
308
+ }
309
+
310
+ .zoneFrame :global(.am-nav .am-item.am-active .am-ico) {
311
+ background: var(--c-blue-cobalt);
312
+ }
313
+
314
+ .zoneFrame :global(.am-nav .am-item .am-l) {
315
+ flex: 1;
316
+ height: 4px;
317
+ background: var(--c-cobalt-200);
318
+ border-radius: 1px;
319
+ }
320
+
321
+ .zoneFrame :global(.am-nav .am-item.am-active .am-l) {
322
+ background: var(--c-cobalt-700);
323
+ height: 5px;
324
+ }
325
+
326
+ .zoneFrame :global(.am-nav .am-footer) {
327
+ margin-top: auto;
328
+ padding-top: 8px;
329
+ border-top: 1px solid var(--c-cobalt-100);
330
+ display: flex;
331
+ flex-direction: column;
332
+ gap: 5px;
333
+ }
334
+
335
+ /* --- Main column --------------------------------------------- */
336
+
337
+ .zoneFrame :global(.am-col) {
338
+ flex: 1;
339
+ padding: 14px;
340
+ display: flex;
341
+ flex-direction: column;
342
+ gap: 10px;
343
+ min-width: 0;
344
+ min-height: 0;
345
+ overflow: hidden;
346
+ }
347
+
348
+ /* --- Page header --------------------------------------------- */
349
+
350
+ .zoneFrame :global(.am-pageHeader) {
351
+ display: flex;
352
+ align-items: center;
353
+ gap: 6px;
354
+ margin-bottom: 4px;
355
+ }
356
+
357
+ .zoneFrame :global(.am-pageHeader .am-title-bar) {
358
+ flex: 1;
359
+ height: 14px;
360
+ background: var(--c-blue-cobalt);
361
+ border-radius: 3px;
362
+ max-width: 45%;
363
+ }
364
+
365
+ .zoneFrame :global(.am-pageHeader .am-spacer) {
366
+ flex: 1;
367
+ }
368
+
369
+ .zoneFrame :global(.am-pageHeader .am-actions) {
370
+ display: flex;
371
+ gap: 4px;
372
+ }
373
+
374
+ .zoneFrame :global(.am-pageHeader .am-actions .am-btn) {
375
+ height: 14px;
376
+ width: 38px;
377
+ background: var(--c-blue-cobalt);
378
+ border-radius: 3px;
379
+ }
380
+
381
+ .zoneFrame :global(.am-pageHeader .am-actions .am-btn.am-ghost) {
382
+ background: white;
383
+ border: 1px solid var(--c-cobalt-200);
384
+ }
385
+
386
+ /* --- KPI strip ------------------------------------------------ */
387
+
388
+ .zoneFrame :global(.am-kpiRow) {
389
+ display: flex;
390
+ gap: 6px;
391
+ }
392
+
393
+ .zoneFrame :global(.am-kpi) {
394
+ flex: 1;
395
+ display: flex;
396
+ align-items: center;
397
+ gap: 6px;
398
+ padding: 7px 8px;
399
+ background: var(--c-cobalt-50);
400
+ border-radius: 4px;
401
+ }
402
+
403
+ .zoneFrame :global(.am-kpi .am-ico) {
404
+ width: 14px;
405
+ height: 16px;
406
+ clip-path: var(--hex-pointy-top);
407
+ background: var(--c-mint-300);
408
+ flex-shrink: 0;
409
+ }
410
+
411
+ .zoneFrame :global(.am-kpi.am-forest .am-ico) {
412
+ background: var(--c-forest-300);
413
+ }
414
+
415
+ .zoneFrame :global(.am-kpi.am-amber .am-ico) {
416
+ background: var(--c-orange-knvb);
417
+ }
418
+
419
+ .zoneFrame :global(.am-kpi .am-meta) {
420
+ flex: 1;
421
+ display: flex;
422
+ flex-direction: column;
423
+ gap: 3px;
424
+ min-width: 0;
425
+ }
426
+
427
+ .zoneFrame :global(.am-kpi .am-num) {
428
+ height: 7px;
429
+ background: var(--c-cobalt-900);
430
+ border-radius: 1px;
431
+ width: 35%;
432
+ }
433
+
434
+ .zoneFrame :global(.am-kpi .am-label) {
435
+ height: 3px;
436
+ background: var(--c-cobalt-400);
437
+ border-radius: 1px;
438
+ width: 70%;
439
+ }
440
+
441
+ /* --- Panel row + panels --------------------------------------- */
442
+
443
+ .zoneFrame :global(.am-panelRow) {
444
+ display: grid;
445
+ grid-template-columns: 1fr 1fr;
446
+ gap: 8px;
447
+ flex: 1;
448
+ min-height: 0;
449
+ }
450
+
451
+ .zoneFrame :global(.am-panel) {
452
+ background: white;
453
+ border: 1px solid var(--c-cobalt-100);
454
+ border-radius: 4px;
455
+ padding: 8px;
456
+ display: flex;
457
+ flex-direction: column;
458
+ gap: 6px;
459
+ min-height: 0;
460
+ overflow: hidden;
461
+ }
462
+
463
+ .zoneFrame :global(.am-panel .am-head) {
464
+ display: flex;
465
+ align-items: center;
466
+ justify-content: space-between;
467
+ gap: 6px;
468
+ }
469
+
470
+ .zoneFrame :global(.am-panel .am-head .am-title) {
471
+ height: 5px;
472
+ background: var(--c-cobalt-700);
473
+ border-radius: 1px;
474
+ width: 35%;
475
+ }
476
+
477
+ .zoneFrame :global(.am-panel .am-stack) {
478
+ display: flex;
479
+ flex-direction: column;
480
+ gap: 4px;
481
+ }
482
+
483
+ .zoneFrame :global(.am-panel .am-item) {
484
+ display: flex;
485
+ align-items: center;
486
+ gap: 6px;
487
+ padding: 3px 0;
488
+ border-bottom: 1px solid var(--c-cobalt-50);
489
+ }
490
+
491
+ .zoneFrame :global(.am-panel .am-item:last-child) {
492
+ border-bottom: 0;
493
+ }
494
+
495
+ .zoneFrame :global(.am-panel .am-item .am-av) {
496
+ width: 12px;
497
+ height: 12px;
498
+ border-radius: 50%;
499
+ background: var(--c-mint-300);
500
+ flex-shrink: 0;
501
+ }
502
+
503
+ .zoneFrame :global(.am-panel .am-item .am-av.am-b) {
504
+ background: var(--c-lavender-300);
505
+ }
506
+
507
+ .zoneFrame :global(.am-panel .am-item .am-lines) {
508
+ flex: 1;
509
+ display: flex;
510
+ flex-direction: column;
511
+ gap: 2px;
512
+ }
513
+
514
+ .zoneFrame :global(.am-panel .am-item .am-l1) {
515
+ height: 4px;
516
+ background: var(--c-cobalt-700);
517
+ border-radius: 1px;
518
+ width: 65%;
519
+ }
520
+
521
+ /* --- Detail / Sidebar (rich) ---------------------------------- */
522
+
523
+ .zoneFrame :global(.am-detail) {
524
+ width: 26%;
525
+ min-width: 130px;
526
+ flex-shrink: 0;
527
+ background: white;
528
+ border-left: 1px solid var(--c-cobalt-100);
529
+ display: flex;
530
+ flex-direction: column;
531
+ }
532
+
533
+ .zoneFrame :global(.am-detail.am-rich .am-sb-head) {
534
+ display: flex;
535
+ align-items: center;
536
+ gap: 6px;
537
+ padding: 10px;
538
+ border-bottom: 1px solid var(--c-cobalt-100);
539
+ }
540
+
541
+ .zoneFrame :global(.am-detail.am-rich .am-sb-head .am-ico) {
542
+ width: 18px;
543
+ height: 18px;
544
+ border-radius: 4px;
545
+ background: var(--c-cobalt-50);
546
+ flex-shrink: 0;
547
+ }
548
+
549
+ .zoneFrame :global(.am-detail.am-rich .am-sb-head .am-meta) {
550
+ flex: 1;
551
+ display: flex;
552
+ flex-direction: column;
553
+ gap: 3px;
554
+ }
555
+
556
+ .zoneFrame :global(.am-detail.am-rich .am-sb-head .am-title) {
557
+ height: 6px;
558
+ background: var(--c-cobalt-900);
559
+ border-radius: 1px;
560
+ width: 50%;
561
+ }
562
+
563
+ .zoneFrame :global(.am-detail.am-rich .am-sb-head .am-desc) {
564
+ height: 3px;
565
+ background: var(--c-cobalt-300);
566
+ border-radius: 1px;
567
+ width: 85%;
568
+ }
569
+
570
+ .zoneFrame :global(.am-detail.am-rich .am-sb-head .am-close) {
571
+ width: 8px;
572
+ height: 8px;
573
+ background: var(--c-cobalt-300);
574
+ flex-shrink: 0;
575
+ }
576
+
577
+ .zoneFrame :global(.am-detail.am-rich .am-sb-tabs) {
578
+ display: flex;
579
+ gap: 4px;
580
+ padding: 4px 10px 0;
581
+ border-bottom: 1px solid var(--c-cobalt-100);
582
+ }
583
+
584
+ .zoneFrame :global(.am-detail.am-rich .am-sb-tab) {
585
+ display: flex;
586
+ align-items: center;
587
+ gap: 4px;
588
+ padding: 4px 6px;
589
+ border-bottom: 2px solid transparent;
590
+ }
591
+
592
+ .zoneFrame :global(.am-detail.am-rich .am-sb-tab.am-active) {
593
+ border-bottom-color: var(--c-blue-cobalt);
594
+ }
595
+
596
+ .zoneFrame :global(.am-detail.am-rich .am-sb-tab .am-ico) {
597
+ width: 7px;
598
+ height: 7px;
599
+ border-radius: 50%;
600
+ background: var(--c-cobalt-300);
601
+ }
602
+
603
+ .zoneFrame :global(.am-detail.am-rich .am-sb-tab.am-active .am-ico) {
604
+ background: var(--c-cobalt-700);
605
+ }
606
+
607
+ .zoneFrame :global(.am-detail.am-rich .am-sb-tab .am-l) {
608
+ height: 3px;
609
+ background: var(--c-cobalt-300);
610
+ width: 24px;
611
+ border-radius: 1px;
612
+ }
613
+
614
+ .zoneFrame :global(.am-detail.am-rich .am-sb-tab.am-active .am-l) {
615
+ background: var(--c-cobalt-700);
616
+ }
617
+
618
+ .zoneFrame :global(.am-detail.am-rich .am-sb-body) {
619
+ padding: 10px;
620
+ display: flex;
621
+ flex-direction: column;
622
+ gap: 7px;
623
+ overflow: hidden;
624
+ }
625
+
626
+ .zoneFrame :global(.am-detail.am-rich .am-sb-input) {
627
+ height: 14px;
628
+ background: white;
629
+ border: 1px solid var(--c-cobalt-200);
630
+ border-radius: 3px;
631
+ }
632
+
633
+ .zoneFrame :global(.am-detail.am-rich .am-sb-filter) {
634
+ display: flex;
635
+ flex-direction: column;
636
+ gap: 4px;
637
+ }
638
+
639
+ .zoneFrame :global(.am-detail.am-rich .am-sb-filter .am-lbl) {
640
+ height: 3px;
641
+ background: var(--c-cobalt-400);
642
+ width: 30%;
643
+ border-radius: 1px;
644
+ }
645
+
646
+ .zoneFrame :global(.am-detail.am-rich .am-sb-filter .am-field) {
647
+ height: 12px;
648
+ background: white;
649
+ border: 1px solid var(--c-cobalt-200);
650
+ border-radius: 2px;
651
+ }
652
+
653
+ /* ============================================================
654
+ Zone-focus overlay — dim everything except the focused atom
655
+ ============================================================ */
656
+
657
+ .zoneFrame :global(.am-topbar),
658
+ .zoneFrame :global(.am-body > .am-nav),
659
+ .zoneFrame :global(.am-body > .am-col),
660
+ .zoneFrame :global(.am-body > .am-detail),
661
+ .zoneFrame :global(.am-pageHeader) {
662
+ transition: opacity 200ms;
663
+ }
664
+
665
+ /* Topbar */
666
+ .focusTopbar :global(.am-body) {
667
+ opacity: 0.25;
668
+ }
669
+ .focusTopbar :global(.am-topbar) {
670
+ box-shadow: 0 0 0 2px var(--c-orange-knvb);
671
+ }
672
+
673
+ /* Left navigation */
674
+ .focusNav :global(.am-topbar),
675
+ .focusNav :global(.am-body > .am-col),
676
+ .focusNav :global(.am-body > .am-detail) {
677
+ opacity: 0.25;
678
+ }
679
+ .focusNav :global(.am-body > .am-nav) {
680
+ box-shadow: inset 0 0 0 2px var(--c-orange-knvb);
681
+ }
682
+
683
+ /* Main column */
684
+ .focusCol :global(.am-topbar),
685
+ .focusCol :global(.am-body > .am-nav),
686
+ .focusCol :global(.am-body > .am-detail) {
687
+ opacity: 0.25;
688
+ }
689
+ .focusCol :global(.am-body > .am-col) {
690
+ box-shadow: inset 0 0 0 2px var(--c-orange-knvb);
691
+ }
692
+
693
+ /* Page header */
694
+ .focusPageHeader :global(.am-topbar),
695
+ .focusPageHeader :global(.am-body > .am-nav),
696
+ .focusPageHeader :global(.am-body > .am-detail),
697
+ .focusPageHeader :global(.am-body > .am-col > *:not(.am-pageHeader)) {
698
+ opacity: 0.25;
699
+ }
700
+ .focusPageHeader :global(.am-pageHeader) {
701
+ box-shadow: 0 0 0 2px var(--c-orange-knvb);
702
+ border-radius: 4px;
703
+ }
704
+
705
+ /* Sidebar */
706
+ .focusDetail :global(.am-topbar),
707
+ .focusDetail :global(.am-body > .am-nav),
708
+ .focusDetail :global(.am-body > .am-col) {
709
+ opacity: 0.25;
710
+ }
711
+ .focusDetail :global(.am-body > .am-detail) {
712
+ box-shadow: inset 0 0 0 2px var(--c-orange-knvb);
713
+ }
@@ -66,6 +66,11 @@ export {Hex, HexPrism, Platform, DomainTree, DiagramPipeline, SideBox, Honeycomb
66
66
  export {default as ComposeBlock} from './ComposeBlock/ComposeBlock.jsx';
67
67
  export {default as AppsGrid} from './AppsGrid/AppsGrid.jsx';
68
68
  export {default as AppMock} from './AppMock/AppMock.jsx';
69
+ export {default as WidgetMock} from './WidgetMock/WidgetMock.jsx';
70
+ export {default as SidebarMock} from './SidebarMock/SidebarMock.jsx';
71
+ export {default as MockScene} from './MockScene/MockScene.jsx';
72
+ export {default as IntegrationIcon} from './IntegrationIcon/IntegrationIcon.jsx';
73
+ export {default as AtomZones} from './AtomZones/AtomZones.jsx';
69
74
  export {default as HexNetwork} from './HexNetwork/HexNetwork.jsx';
70
75
  export {default as Showcase} from './Showcase/Showcase.jsx';
71
76
  export {default as RotatingCards} from './RotatingCards/RotatingCards.jsx';