@conduction/docusaurus-preset 3.33.0 → 3.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/ANIMATION_ROADMAP.md +129 -0
  2. package/MISSING_COMPONENTS.md +15 -5
  3. package/package.json +3 -2
  4. package/src/components/AgentTrace/AgentTrace.jsx +26 -5
  5. package/src/components/AgentTrace/AgentTrace.module.css +41 -2
  6. package/src/components/AgentTrace/__tests__/AgentTrace.render.test.js +108 -0
  7. package/src/components/AppMock/AppMock.jsx +14 -5
  8. package/src/components/AppMock/AppMock.module.css +1702 -0
  9. package/src/components/AppMock/__tests__/AppMock.render.test.js +329 -0
  10. package/src/components/AppMock/variants/DeciDeskMock.jsx +46 -5
  11. package/src/components/AppMock/variants/DocuDeskMock.jsx +39 -9
  12. package/src/components/AppMock/variants/DoriathMock.jsx +28 -13
  13. package/src/components/AppMock/variants/HermiqMock.jsx +35 -15
  14. package/src/components/AppMock/variants/HrmqMock.jsx +46 -28
  15. package/src/components/AppMock/variants/LarpingAppMock.jsx +36 -7
  16. package/src/components/AppMock/variants/LaunchPadBiMock.jsx +12 -5
  17. package/src/components/AppMock/variants/LaunchPadTilesMock.jsx +6 -1
  18. package/src/components/AppMock/variants/LaunchPadWidgetsMock.jsx +17 -8
  19. package/src/components/AppMock/variants/NLDesignMock.jsx +15 -4
  20. package/src/components/AppMock/variants/OpenBuildMock.jsx +20 -5
  21. package/src/components/AppMock/variants/OpenCatalogiMock.jsx +23 -4
  22. package/src/components/AppMock/variants/OpenConnectorMock.jsx +25 -3
  23. package/src/components/AppMock/variants/OpenRegisterMock.jsx +13 -2
  24. package/src/components/AppMock/variants/PipelinQMock.jsx +12 -2
  25. package/src/components/AppMock/variants/PortaliqMock.jsx +21 -9
  26. package/src/components/AppMock/variants/ProcestMock.jsx +34 -7
  27. package/src/components/AppMock/variants/ScholiqMock.jsx +12 -6
  28. package/src/components/AppMock/variants/ShillinqMock.jsx +33 -17
  29. package/src/components/AppMock/variants/SoftwareCatalogMock.jsx +15 -5
  30. package/src/components/AppMock/variants/ZaakAfhandelAppMock.jsx +19 -4
  31. package/src/components/FlowMock/FlowMock.jsx +5 -3
  32. package/src/components/FlowMock/FlowMock.module.css +36 -9
  33. package/src/components/FlowMock/__tests__/FlowMock.render.test.js +83 -0
  34. package/src/components/LeafMock/LeafMock.jsx +23 -8
  35. package/src/components/LeafMock/LeafMock.module.css +123 -0
  36. package/src/components/LeafMock/__tests__/LeafMock.render.test.js +105 -0
  37. package/src/components/MockScene/MockScene.jsx +16 -2
  38. package/src/components/MockScene/MockScene.module.css +22 -2
  39. package/src/components/MockScene/__tests__/MockScene.render.test.js +101 -0
  40. package/src/components/SidebarMock/SidebarMock.jsx +29 -2
  41. package/src/components/SidebarMock/__tests__/SidebarMock.render.test.js +115 -0
  42. package/src/components/WidgetMock/WidgetMock.jsx +35 -14
  43. package/src/components/WidgetMock/__tests__/WidgetMock.render.test.js +125 -0
  44. package/src/components/WidgetMock/variants/DocuDeskAnonymise.jsx +6 -1
@@ -1,21 +1,25 @@
1
1
  /**
2
- * HRMQ abstract — people administration.
2
+ * HRMQ abstract — hours administration.
3
3
  *
4
- * Inferred from the app role (HR: employees, contracts, leave): a
5
- * people list with hex avatars next to a leave-balance card of
6
- * labelled horizontal bars. Tone: mint the team is in order.
4
+ * Content rework (wave 4): the earlier people-list + leave-balance
5
+ * pair misrepresented the app (HRMQ's daily surface is hours and
6
+ * approval, not a personnel directory). The mock now shows the
7
+ * timesheet week — five day columns of hour bars plus a submit
8
+ * button — next to an approval card: the submitted week arriving as
9
+ * a row, its pip ticking mint on approval, and a payroll counter
10
+ * that grows when the approved hours land. Tone: mint — the team's
11
+ * hours are in order.
12
+ *
13
+ * Animation: day bars fill in a stagger → submit press → the
14
+ * approval row's pip ticks mint → the payroll counter widens.
15
+ * Base styles are the approved end state.
7
16
  */
8
17
 
9
18
  import React from 'react';
10
19
  import styles from '../AppMock.module.css';
11
20
 
12
- const PEOPLE = ['var(--c-mint-500)', 'var(--c-mint-300)', 'var(--c-forest-300)', 'var(--c-mint-300)', 'var(--c-mint-500)'];
13
- const BALANCES = [
14
- {fill: '72%', shade: 'var(--c-mint-500)'},
15
- {fill: '45%', shade: 'var(--c-mint-500)'},
16
- {fill: '88%', shade: 'var(--c-mint-300)'},
17
- {fill: '20%', shade: 'var(--c-mint-300)'},
18
- ];
21
+ /* Hour-bar heights for the five day columns of the week. */
22
+ const WEEK = ['70%', '85%', '60%', '90%', '45%'];
19
23
 
20
24
  export default function HrmqMock() {
21
25
  return (
@@ -27,7 +31,7 @@ export default function HrmqMock() {
27
31
  <div className={styles.bell}></div>
28
32
  <div className={styles.avatar}></div>
29
33
  </div>
30
- <div className={[styles.body, styles.decidesk].filter(Boolean).join(' ')}>
34
+ <div className={[styles.body, styles.decidesk, styles.hrmq].filter(Boolean).join(' ')}>
31
35
  <div className={styles.nav}>
32
36
  <div className={styles.navHead}><div className={styles.h}></div><div className={styles.l}></div></div>
33
37
  {[true, false, false, false, false].map((active, i) => (
@@ -45,29 +49,43 @@ export default function HrmqMock() {
45
49
  </div>
46
50
  </div>
47
51
  <div className={styles.panelRow} style={{gridTemplateColumns: '1.2fr 1fr'}}>
48
- {/* People list hex avatars */}
49
- <div className={styles.panel}>
52
+ {/* Timesheetthe week's hour bars + submit */}
53
+ <div className={[styles.panel, styles.timesheet].join(' ')}>
50
54
  <div className={styles.head}><div className={styles.title}></div></div>
51
- <div className={styles.stack}>
52
- {PEOPLE.map((shade, i) => (
53
- <div key={i} className={styles.item}>
54
- <div style={{width: 13, height: 15, clipPath: 'var(--hex-pointy-top)', background: shade, flexShrink: 0}}></div>
55
- <div className={styles.lines}><div className={styles.l1}></div><div className={styles.l2}></div></div>
55
+ <div className={styles.week}>
56
+ {WEEK.map((h, i) => (
57
+ <div key={i} className={styles.dayCol}>
58
+ <div className={styles.dayBar} style={{height: h}}></div>
59
+ <div className={styles.dayLabel}></div>
56
60
  </div>
57
61
  ))}
58
62
  </div>
63
+ <div className={styles.sheetFoot}>
64
+ <div className={styles.sheetSum}></div>
65
+ <div className={[styles.btn, styles.submitBtn].join(' ')}></div>
66
+ </div>
59
67
  </div>
60
- {/* Leave-balance cardlabelled bars */}
61
- <div className={styles.panel}>
68
+ {/* Approval + payroll the submitted week arrives, is
69
+ approved (mint tick), and the payroll counter grows. */}
70
+ <div className={[styles.panel, styles.approval].join(' ')}>
62
71
  <div className={styles.head}><div className={styles.title}></div></div>
63
- {BALANCES.map(({fill, shade}, i) => (
64
- <div key={i} style={{display: 'flex', flexDirection: 'column', gap: 3}}>
65
- <div className={styles.row + ' ' + styles.short} style={{height: 3}}></div>
66
- <div style={{height: 5, background: 'var(--c-cobalt-100)', borderRadius: 2}}>
67
- <div style={{width: fill, height: 5, background: shade, borderRadius: 2}}></div>
68
- </div>
72
+ <div className={styles.stack}>
73
+ <div className={[styles.item, styles.approveRow].join(' ')}>
74
+ <div className={styles.av}></div>
75
+ <div className={styles.lines}><div className={styles.l1}></div><div className={styles.l2}></div></div>
76
+ <div className={styles.approvePip}></div>
77
+ </div>
78
+ <div className={styles.item}>
79
+ <div className={[styles.av, styles.b].join(' ')}></div>
80
+ <div className={styles.lines}><div className={styles.l1}></div><div className={styles.l2}></div></div>
81
+ <div className={styles.donePip}></div>
69
82
  </div>
70
- ))}
83
+ </div>
84
+ {/* Payroll counter — widens when the approval lands */}
85
+ <div className={styles.payroll}>
86
+ <div className={styles.pLabel}></div>
87
+ <div className={styles.pNum}></div>
88
+ </div>
71
89
  </div>
72
90
  </div>
73
91
  </div>
@@ -6,6 +6,12 @@
6
6
  * with hex avatars in different family tones) plus a scene timeline
7
7
  * across the top so a session organiser can move stages forward. Left
8
8
  * nav for characters / scenes / NPCs / factions / rules / archive.
9
+ *
10
+ * Animation (wave 4, the XP ripple): the second character card lifts,
11
+ * an XP hex token rises from it to the scene timeline's active stage,
12
+ * the stage hex pulses as it absorbs the token, and every character
13
+ * card's text rows grow in a stagger — the whole party levelling from
14
+ * the played scene. Base styles are the settled (post-XP) end state.
9
15
  */
10
16
 
11
17
  import React from 'react';
@@ -22,7 +28,7 @@ export default function LarpingAppMock() {
22
28
  <div className={styles.bell}></div>
23
29
  <div className={styles.avatar}></div>
24
30
  </div>
25
- <div className={[styles.body, styles.opencatalogi].filter(Boolean).join(' ')}>
31
+ <div className={[styles.body, styles.opencatalogi, styles.larping].filter(Boolean).join(' ')}>
26
32
  <div className={styles.nav}>
27
33
  <div className={styles.navHead}><div className={styles.h}></div><div className={styles.l}></div></div>
28
34
  {[true, false, false, false, false, false].map((active, i) => (
@@ -33,16 +39,36 @@ export default function LarpingAppMock() {
33
39
  ))}
34
40
  </div>
35
41
  <div className={styles.col}>
36
- {/* Scene timeline (one done, one active in orange, three to-do) */}
37
- <div className={[styles.w, styles['w-graph-bar']].join(' ')} style={{minHeight: 0}}>
38
- <div className={styles.wHead}>
39
- <div className={styles.h}></div><div className={styles.t}></div>
42
+ {/* Scene timeline (one done, one active in orange the
43
+ variant's single orange — three to-do). Reuses the
44
+ procest timeline atoms; the wrapper div provides the
45
+ `.procest` scope those styles require. The previous
46
+ markup here was an empty w-graph-bar shell that rendered
47
+ nothing but its header. */}
48
+ <div className={styles.procest}>
49
+ <div className={styles.timeline}>
50
+ <div className={styles.step}>
51
+ <div className={styles.h}></div><div className={styles.label}></div>
52
+ </div>
53
+ <div className={[styles.step, styles.now].join(' ')}>
54
+ <div className={styles.h}></div><div className={styles.label}></div>
55
+ </div>
56
+ <div className={[styles.step, styles.todo].join(' ')}>
57
+ <div className={styles.h}></div><div className={styles.label}></div>
58
+ </div>
59
+ <div className={[styles.step, styles.todo].join(' ')}>
60
+ <div className={styles.h}></div><div className={styles.label}></div>
61
+ </div>
62
+ <div className={[styles.step, styles.todo].join(' ')}>
63
+ <div className={styles.h}></div><div className={styles.label}></div>
64
+ </div>
40
65
  </div>
41
66
  </div>
42
- {/* Character grid */}
67
+ {/* Character grid. Card 2 (.xpSource) lifts and releases the
68
+ XP token that travels up to the timeline's active stage. */}
43
69
  <div className={styles.grid}>
44
70
  {charTones.map((cls, i) => (
45
- <div key={i} className={[styles.card, cls && styles[cls]].filter(Boolean).join(' ')}>
71
+ <div key={i} className={[styles.card, cls && styles[cls], i === 1 && styles.xpSource].filter(Boolean).join(' ')}>
46
72
  <div className={styles.ico}></div>
47
73
  <div className={styles.row + ' ' + styles.head}></div>
48
74
  <div className={styles.row + ' ' + styles.short}></div>
@@ -52,6 +78,9 @@ export default function LarpingAppMock() {
52
78
  </div>
53
79
  ))}
54
80
  </div>
81
+ {/* XP token — travels from the lifted card to the timeline.
82
+ Hidden at rest and in static frames. */}
83
+ <div className={styles.xpToken}></div>
55
84
  </div>
56
85
  </div>
57
86
  </>
@@ -5,6 +5,13 @@
5
5
  * on a register without ETL. The mock shows four graph cards in a
6
6
  * 2×2 grid (bar chart, line chart, donut KPI, second bar with a
7
7
  * different accent), plus a ranked-list table widget on the right.
8
+ *
9
+ * Animated (9s loop, --am-dur): the charts draw themselves — bars
10
+ * grow from the axis in a stagger, the line draws along its path
11
+ * (pathLength="1" dash technique) and its end dot pops, the donut
12
+ * sweeps in, and the KPI delta bars fade up (inline delays).
13
+ * `running={false}` / prefers-reduced-motion show the drawn charts.
14
+ * Keyframes live in AppMock.module.css (`.lpBi` section).
8
15
  */
9
16
 
10
17
  import React from 'react';
@@ -20,7 +27,7 @@ export default function LaunchPadBiMock() {
20
27
  <div className={styles.bell}></div>
21
28
  <div className={styles.avatar}></div>
22
29
  </div>
23
- <div className={[styles.body, styles.launchpad].filter(Boolean).join(' ')}>
30
+ <div className={[styles.body, styles.launchpad, styles.lpBi].filter(Boolean).join(' ')}>
24
31
  <div className={styles.grid}>
25
32
  {/* Column 1: Bar chart on top, line chart below */}
26
33
  <div className={styles.col}>
@@ -45,7 +52,7 @@ export default function LaunchPadBiMock() {
45
52
  <div className={styles.chart}>
46
53
  <svg viewBox="0 0 100 40" preserveAspectRatio="none">
47
54
  <path className={styles.fill} d="M0,32 L14,24 L28,28 L42,18 L56,22 L70,12 L84,16 L100,8 L100,40 L0,40 Z"/>
48
- <path className={styles.stroke} d="M0,32 L14,24 L28,28 L42,18 L56,22 L70,12 L84,16 L100,8"/>
55
+ <path className={styles.stroke} pathLength="1" d="M0,32 L14,24 L28,28 L42,18 L56,22 L70,12 L84,16 L100,8"/>
49
56
  <circle className={styles.dot} cx="100" cy="8" r="2.5"/>
50
57
  </svg>
51
58
  </div>
@@ -89,7 +96,7 @@ export default function LaunchPadBiMock() {
89
96
  </div>
90
97
  <div style={{display: 'flex', alignItems: 'baseline', gap: 4}}>
91
98
  <div style={{height: 12, width: 28, background: 'var(--c-cobalt-900)', borderRadius: 1}}></div>
92
- <div style={{height: 4, width: 16, background: 'var(--c-mint-500)', borderRadius: 1}}></div>
99
+ <div className={styles.biDelta} style={{height: 4, width: 16, background: 'var(--c-mint-500)', borderRadius: 1}}></div>
93
100
  </div>
94
101
  <div style={{height: 3, width: '70%', background: 'var(--c-cobalt-200)', borderRadius: 1}}></div>
95
102
  </div>
@@ -99,7 +106,7 @@ export default function LaunchPadBiMock() {
99
106
  </div>
100
107
  <div style={{display: 'flex', alignItems: 'baseline', gap: 4}}>
101
108
  <div style={{height: 12, width: 22, background: 'var(--c-cobalt-900)', borderRadius: 1}}></div>
102
- <div style={{height: 4, width: 14, background: 'var(--c-orange-knvb)', borderRadius: 1}}></div>
109
+ <div className={styles.biDelta} style={{height: 4, width: 14, background: 'var(--c-orange-knvb)', borderRadius: 1, animationDelay: '0.2s'}}></div>
103
110
  </div>
104
111
  <div style={{height: 3, width: '60%', background: 'var(--c-cobalt-200)', borderRadius: 1}}></div>
105
112
  </div>
@@ -109,7 +116,7 @@ export default function LaunchPadBiMock() {
109
116
  </div>
110
117
  <div style={{display: 'flex', alignItems: 'baseline', gap: 4}}>
111
118
  <div style={{height: 12, width: 30, background: 'var(--c-cobalt-900)', borderRadius: 1}}></div>
112
- <div style={{height: 4, width: 12, background: 'var(--c-mint-500)', borderRadius: 1}}></div>
119
+ <div className={styles.biDelta} style={{height: 4, width: 12, background: 'var(--c-mint-500)', borderRadius: 1, animationDelay: '0.4s'}}></div>
113
120
  </div>
114
121
  <div style={{height: 3, width: '80%', background: 'var(--c-cobalt-200)', borderRadius: 1}}></div>
115
122
  </div>
@@ -7,6 +7,11 @@
7
7
  * a sub-grid of further tiles. The mock pictures exactly that mix:
8
8
  * four launcher tiles top-left, a 2×2 sub-grid bottom-left ("custom
9
9
  * tile group"), and two info widgets right.
10
+ *
11
+ * Animated (7s loop, --am-dur): the custom tile group is pressed
12
+ * (a short scale dip) and unfolds its four sub-tiles in a stagger.
13
+ * `running={false}` / prefers-reduced-motion show the unfolded
14
+ * group. Keyframes live in AppMock.module.css (`.lpTiles` section).
10
15
  */
11
16
 
12
17
  import React from 'react';
@@ -22,7 +27,7 @@ export default function LaunchPadTilesMock() {
22
27
  <div className={styles.bell}></div>
23
28
  <div className={styles.avatar}></div>
24
29
  </div>
25
- <div className={[styles.body, styles.launchpad].filter(Boolean).join(' ')}>
30
+ <div className={[styles.body, styles.launchpad, styles.lpTiles].filter(Boolean).join(' ')}>
26
31
  <div className={styles.grid}>
27
32
  {/* Column 1: Launcher tiles in cobalt + KNVB */}
28
33
  <div className={styles.col}>
@@ -11,11 +11,20 @@
11
11
  * - Jira → external-app status board
12
12
  * - RSS → headlines feed
13
13
  * - Video → video-call shortcut
14
+ *
15
+ * Animated (10s loop, --am-dur): the dashboard assembles — the seven
16
+ * widgets arrive one by one on a 900ms stagger (inline
17
+ * animation-delay, reading order), hold, then fade for the reset.
18
+ * `running={false}` / prefers-reduced-motion show the assembled
19
+ * board. Keyframes live in AppMock.module.css (`.lpWidgets` section).
14
20
  */
15
21
 
16
22
  import React from 'react';
17
23
  import styles from '../AppMock.module.css';
18
24
 
25
+ /* Per-widget arrival delay on the shared stagger. */
26
+ const ARRIVE = (i) => ({animationDelay: `${i * 900}ms`});
27
+
19
28
  export default function LaunchPadWidgetsMock() {
20
29
  return (
21
30
  <>
@@ -26,11 +35,11 @@ export default function LaunchPadWidgetsMock() {
26
35
  <div className={styles.bell}></div>
27
36
  <div className={styles.avatar}></div>
28
37
  </div>
29
- <div className={[styles.body, styles.launchpad].filter(Boolean).join(' ')}>
38
+ <div className={[styles.body, styles.launchpad, styles.lpWidgets].filter(Boolean).join(' ')}>
30
39
  <div className={styles.grid}>
31
40
  {/* Column 1: Procest werkvoorraad + DocuDesk upload */}
32
41
  <div className={styles.col}>
33
- <div className={[styles.w, styles['w-werkvoorraad']].join(' ')}>
42
+ <div className={[styles.w, styles['w-werkvoorraad']].join(' ')} style={ARRIVE(0)}>
34
43
  <div className={styles.wHead}>
35
44
  <div className={styles.h}></div><div className={styles.t}></div>
36
45
  </div>
@@ -42,7 +51,7 @@ export default function LaunchPadWidgetsMock() {
42
51
  <div className={styles.item}><div className={styles.stage}></div><div className={styles.l1}></div><div className={[styles.av, styles.b].join(' ')}></div></div>
43
52
  </div>
44
53
  </div>
45
- <div className={[styles.w, styles['w-upload']].join(' ')}>
54
+ <div className={[styles.w, styles['w-upload']].join(' ')} style={ARRIVE(1)}>
46
55
  <div className={styles.wHead}>
47
56
  <div className={styles.h}></div><div className={styles.t}></div>
48
57
  </div>
@@ -53,7 +62,7 @@ export default function LaunchPadWidgetsMock() {
53
62
  </div>
54
63
  </div>
55
64
  {/* Column 2: Mail (Important mail) */}
56
- <div className={[styles.w, styles['w-mail']].join(' ')}>
65
+ <div className={[styles.w, styles['w-mail']].join(' ')} style={ARRIVE(2)}>
57
66
  <div className={styles.wHead}>
58
67
  <div className={styles.h}></div><div className={styles.t}></div>
59
68
  </div>
@@ -71,7 +80,7 @@ export default function LaunchPadWidgetsMock() {
71
80
  </div>
72
81
  {/* Column 3: Jira status board + RSS feed */}
73
82
  <div className={styles.col}>
74
- <div className={[styles.w, styles['w-jira']].join(' ')}>
83
+ <div className={[styles.w, styles['w-jira']].join(' ')} style={ARRIVE(3)}>
75
84
  <div className={styles.wHead}>
76
85
  <div className={styles.h}></div><div className={styles.t}></div>
77
86
  </div>
@@ -83,7 +92,7 @@ export default function LaunchPadWidgetsMock() {
83
92
  <div className={styles.item}><div className={styles.id}></div><div className={styles.l}></div><div className={styles.pip}></div></div>
84
93
  </div>
85
94
  </div>
86
- <div className={[styles.w, styles['w-rss']].join(' ')}>
95
+ <div className={[styles.w, styles['w-rss']].join(' ')} style={ARRIVE(4)}>
87
96
  <div className={styles.wHead}>
88
97
  <div className={styles.h}></div><div className={styles.t}></div>
89
98
  </div>
@@ -96,7 +105,7 @@ export default function LaunchPadWidgetsMock() {
96
105
  </div>
97
106
  {/* Column 4: Calendar + Video call shortcut */}
98
107
  <div className={styles.col}>
99
- <div className={[styles.w, styles['w-calendar']].join(' ')}>
108
+ <div className={[styles.w, styles['w-calendar']].join(' ')} style={ARRIVE(5)}>
100
109
  <div className={styles.wHead}>
101
110
  <div className={styles.h}></div><div className={styles.t}></div>
102
111
  </div>
@@ -106,7 +115,7 @@ export default function LaunchPadWidgetsMock() {
106
115
  ))}
107
116
  </div>
108
117
  </div>
109
- <div className={[styles.w, styles['w-video']].join(' ')}>
118
+ <div className={[styles.w, styles['w-video']].join(' ')} style={ARRIVE(6)}>
110
119
  <div className={styles.wHead}>
111
120
  <div className={styles.h}></div><div className={styles.t}></div>
112
121
  </div>
@@ -5,6 +5,14 @@
5
5
  * centre shows a settings layout with a colour-swatch row, a type
6
6
  * specimen, and a component preview block. Left nav for theme /
7
7
  * colours / typography / spacing / components / overrides.
8
+ *
9
+ * Animated (6s loop, --am-dur): the lavender swatch is selected (a
10
+ * cobalt focus ring pops on it), the component preview rethemes in a
11
+ * cascade (button, then status pill crossfade to lavender), and the
12
+ * type-scale bars restretch as if the theme changed the scale. The
13
+ * loop reverts by crossfading back. `running={false}` /
14
+ * prefers-reduced-motion show the resting cobalt/mint theme with no
15
+ * ring. Keyframes live in AppMock.module.css (`.nldesign` section).
8
16
  */
9
17
 
10
18
  import React from 'react';
@@ -20,7 +28,7 @@ export default function NLDesignMock() {
20
28
  <div className={styles.bell}></div>
21
29
  <div className={styles.avatar}></div>
22
30
  </div>
23
- <div className={[styles.body, styles.openregister].filter(Boolean).join(' ')}>
31
+ <div className={[styles.body, styles.openregister, styles.nldesign].filter(Boolean).join(' ')}>
24
32
  <div className={styles.nav}>
25
33
  <div className={styles.navHead}><div className={styles.h}></div><div className={styles.l}></div></div>
26
34
  {[true, false, false, false, false, false].map((active, i) => (
@@ -35,15 +43,16 @@ export default function NLDesignMock() {
35
43
  <div className={styles.panel}>
36
44
  <div className={styles.head}><div className={styles.title}></div></div>
37
45
  <div style={{display: 'flex', gap: 6, flexWrap: 'wrap'}}>
46
+ {/* Index 3 (lavender) is the swatch the animation selects. */}
38
47
  {['var(--c-blue-cobalt)','var(--c-orange-knvb)','var(--c-mint-500)','var(--c-lavender-500)','var(--c-forest-500)','var(--c-terracotta-500)','var(--c-cobalt-300)','var(--c-cobalt-100)'].map((bg, i) => (
39
- <span key={i} style={{width: 22, height: 22, borderRadius: 4, background: bg}}></span>
48
+ <span key={i} className={[styles.swatch, i === 3 && styles.swatchSel].filter(Boolean).join(' ')} style={{background: bg}}></span>
40
49
  ))}
41
50
  </div>
42
51
  </div>
43
52
  {/* Type specimen */}
44
53
  <div className={styles.panel}>
45
54
  <div className={styles.head}><div className={styles.title}></div></div>
46
- <div style={{display: 'flex', alignItems: 'baseline', gap: 8}}>
55
+ <div className={styles.typeRow} style={{display: 'flex', alignItems: 'baseline', gap: 8}}>
47
56
  <div style={{height: 14, width: 18, background: 'var(--c-cobalt-900)', borderRadius: 1}}></div>
48
57
  <div style={{height: 11, width: 14, background: 'var(--c-cobalt-700)', borderRadius: 1}}></div>
49
58
  <div style={{height: 8, width: 12, background: 'var(--c-cobalt-400)', borderRadius: 1}}></div>
@@ -56,7 +65,9 @@ export default function NLDesignMock() {
56
65
  {/* Component preview */}
57
66
  <div className={styles.panel}>
58
67
  <div className={styles.head}><div className={styles.title}></div></div>
59
- <div style={{display: 'flex', gap: 6, flexWrap: 'wrap'}}>
68
+ {/* The .actions wrapper is required for .btn to pick up its
69
+ styles (the buttons rendered invisible without it). */}
70
+ <div className={styles.actions} style={{alignItems: 'center', flexWrap: 'wrap'}}>
60
71
  <div className={styles.btn}></div>
61
72
  <div className={styles.btn + ' ' + styles.ghost}></div>
62
73
  <div className={styles.statusPill}><div className={styles.h}></div><div className={styles.t}></div></div>
@@ -7,6 +7,12 @@
7
7
  * Published / Templates / Versions) over two panels — a virtual-app card
8
8
  * list ("Virtual apps") and a template-catalogue list ("Templates").
9
9
  * Right rail abstracts the per-app manifest/schema editor.
10
+ *
11
+ * Animation (wave 4): the top template row highlights, a ghost chip
12
+ * travels from the template catalogue into the virtual-apps list, the
13
+ * new app row lands there, the first KPI widens, and the published
14
+ * KPI's hex pulses mint — template to running app in one loop. Base
15
+ * styles are the published end state.
10
16
  */
11
17
 
12
18
  import React from 'react';
@@ -40,11 +46,11 @@ export default function OpenBuildMock({ sidebar = null }) {
40
46
  <div className={styles.col}>
41
47
  {/* KPI strip: Virtual apps / Published / Templates / Versions */}
42
48
  <div className={styles.kpiRow}>
43
- <div className={styles.kpi}>
49
+ <div className={[styles.kpi, styles.kpiGrow].join(' ')}>
44
50
  <div className={styles.ico}></div>
45
51
  <div className={styles.meta}><div className={styles.num}></div><div className={styles.label}></div></div>
46
52
  </div>
47
- <div className={[styles.kpi, styles.forest].join(' ')}>
53
+ <div className={[styles.kpi, styles.forest, styles.publishedKpi].join(' ')}>
48
54
  <div className={styles.ico}></div>
49
55
  <div className={styles.meta}><div className={styles.num}></div><div className={styles.label}></div></div>
50
56
  </div>
@@ -57,12 +63,18 @@ export default function OpenBuildMock({ sidebar = null }) {
57
63
  <div className={styles.meta}><div className={styles.num}></div><div className={styles.label}></div></div>
58
64
  </div>
59
65
  </div>
60
- {/* Virtual-app card list + template catalogue */}
66
+ {/* Virtual-app card list + template catalogue. The ghost
67
+ chip travels template row → apps list; the new app row
68
+ (.newApp) lands at the top of the virtual-apps stack. */}
61
69
  <div className={styles.panelRow}>
62
70
  <div className={styles.panel}>
63
71
  <div className={styles.head}><div className={styles.title}></div></div>
64
72
  <div className={styles.stack}>
65
- {['b','d','a','c'].map((cls, i) => (
73
+ <div className={[styles.item, styles.newApp].join(' ')}>
74
+ <div className={[styles.av, styles.b].join(' ')}></div>
75
+ <div className={styles.lines}><div className={styles.l1}></div><div className={styles.l2}></div></div>
76
+ </div>
77
+ {['d','a','c'].map((cls, i) => (
66
78
  <div key={i} className={styles.item}>
67
79
  <div className={[styles.av, styles[cls]].join(' ')}></div>
68
80
  <div className={styles.lines}><div className={styles.l1}></div><div className={styles.l2}></div></div>
@@ -74,13 +86,16 @@ export default function OpenBuildMock({ sidebar = null }) {
74
86
  <div className={styles.head}><div className={styles.title}></div></div>
75
87
  <div className={styles.stack}>
76
88
  {[0,1,2,3].map(i => (
77
- <div key={i} className={styles.item}>
89
+ <div key={i} className={[styles.item, i === 0 && styles.tplSource].filter(Boolean).join(' ')}>
78
90
  <div className={styles.lines}><div className={styles.l1}></div></div>
79
91
  </div>
80
92
  ))}
81
93
  </div>
82
94
  </div>
83
95
  </div>
96
+ {/* Ghost chip — travels from the template catalogue into the
97
+ virtual-apps list. Hidden at rest and in static frames. */}
98
+ <div className={styles.buildGhost}></div>
84
99
  </div>
85
100
  {/* Right rail: per-app manifest / schema editor. When AppMock passes
86
101
  a `sidebar` prop it renders there instead of this placeholder. */}
@@ -5,13 +5,28 @@
5
5
  * search across registers"): centre is a 3×2 grid of catalogue cards,
6
6
  * each with a hex glyph in a different family colour to signal the
7
7
  * categorical mix. Left nav for catalogues / publications / sources.
8
+ *
9
+ * Animation (wave 2): a query types into the search bar, the grid
10
+ * dims, the three matching cards snap back to full strength, and
11
+ * their status pills tick mint. Base styles are the filtered end
12
+ * state (non-matches dimmed); keyframes replay the unfiltered
13
+ * before-state and the search.
8
14
  */
9
15
 
10
16
  import React from 'react';
11
17
  import styles from '../AppMock.module.css';
12
18
 
19
+ /* Cards 1, 3 and 5 (indices 0/2/4) match the query; the others dim. */
20
+ const CARDS = [
21
+ {tone: '', match: true},
22
+ {tone: 'b', match: false},
23
+ {tone: 'c', match: true},
24
+ {tone: 'd', match: false},
25
+ {tone: 'e', match: true},
26
+ {tone: '', match: false},
27
+ ];
28
+
13
29
  export default function OpenCatalogiMock() {
14
- const cards = ['', 'b', 'c', 'd', 'e', ''];
15
30
  return (
16
31
  <>
17
32
  <div className={styles.topbar}>
@@ -36,14 +51,18 @@ export default function OpenCatalogiMock() {
36
51
  <div className={styles.col}>
37
52
  <div className={styles.head}>
38
53
  <div className={styles.row + ' ' + styles.head} style={{width: 30}}></div>
54
+ {/* Federated search bar — the query types in, the grid filters */}
55
+ <div className={styles.search}>
56
+ <div className={styles.sIco}></div>
57
+ <div className={styles.q}></div>
58
+ </div>
39
59
  <div className={styles.actions}>
40
- <div className={styles.btn + ' ' + styles.ghost}></div>
41
60
  <div className={styles.btn}></div>
42
61
  </div>
43
62
  </div>
44
63
  <div className={styles.grid}>
45
- {cards.map((cls, i) => (
46
- <div key={i} className={[styles.card, cls && styles[cls]].filter(Boolean).join(' ')}>
64
+ {CARDS.map(({tone, match}, i) => (
65
+ <div key={i} className={[styles.card, tone && styles[tone], match ? styles.match : styles.dim].filter(Boolean).join(' ')}>
47
66
  <div className={styles.ico}></div>
48
67
  <div className={styles.row + ' ' + styles.head}></div>
49
68
  <div className={styles.row}></div>
@@ -6,6 +6,11 @@
6
6
  * pipeline (lavender source → cobalt connector → forest target), with
7
7
  * a status table below for recent runs. Left nav for sources, jobs,
8
8
  * mappings, sync logs, schedules.
9
+ *
10
+ * Animation (wave 2): a lavender record dot travels source →
11
+ * connector, re-emerges forest on the far side → target (the mapping
12
+ * made visible), then a new run row inserts at the top of the runs
13
+ * table and ticks mint. Base styles are the completed end state.
9
14
  */
10
15
 
11
16
  import React from 'react';
@@ -45,12 +50,18 @@ export default function OpenConnectorMock() {
45
50
  <div className={styles.ico}></div>
46
51
  <div className={styles.row + ' ' + styles.short}></div>
47
52
  </div>
48
- <div className={styles.arrow}></div>
53
+ <div className={styles.arrow}>
54
+ {/* Record dot, lavender leg: source → connector */}
55
+ <div className={styles.travelDotA}></div>
56
+ </div>
49
57
  <div className={styles.conn}>
50
58
  <div className={styles.ico}></div>
51
59
  <div className={styles.label}></div>
52
60
  </div>
53
- <div className={styles.arrow}></div>
61
+ <div className={styles.arrow}>
62
+ {/* Record dot, forest leg: connector → target */}
63
+ <div className={styles.travelDotB}></div>
64
+ </div>
54
65
  <div className={styles.target}>
55
66
  <div className={styles.ico}></div>
56
67
  <div className={styles.row + ' ' + styles.short}></div>
@@ -64,7 +75,18 @@ export default function OpenConnectorMock() {
64
75
  </div>
65
76
  </div>
66
77
  <div className={styles.stack}>
67
- {['a','d','b','c'].map((cls, i) => (
78
+ {/* The freshly-inserted run row: slides in when the dot
79
+ lands, its trailing pip ticks mint. Present (mint)
80
+ in the static end state. */}
81
+ <div className={[styles.item, styles.newRun].join(' ')}>
82
+ <div className={[styles.av, styles.d].join(' ')}></div>
83
+ <div className={styles.lines}>
84
+ <div className={styles.l1}></div>
85
+ <div className={styles.l2}></div>
86
+ </div>
87
+ <div className={styles.runTick}></div>
88
+ </div>
89
+ {['a','d','b'].map((cls, i) => (
68
90
  <div key={i} className={styles.item}>
69
91
  <div className={[styles.av, styles[cls]].join(' ')}></div>
70
92
  <div className={styles.lines}>
@@ -5,6 +5,11 @@
5
5
  * Centre is the canonical "Dashboard" view: KPI strip top, two
6
6
  * side-by-side tables ("Popular Search Terms" / "Objects by Register"),
7
7
  * second row of two more. Right rail shows Filter Statistics + Totals.
8
+ *
9
+ * Animation (wave 2): a new object row lands in the "Objects by
10
+ * Register" table, the first KPI's number widens to absorb the count,
11
+ * and the right-rail statistics rows repaint in a stagger — the
12
+ * dashboard reacting to a write. Base styles are the landed end state.
8
13
  */
9
14
 
10
15
  import React from 'react';
@@ -38,7 +43,7 @@ export default function OpenRegisterMock({ sidebar = null }) {
38
43
  <div className={styles.col}>
39
44
  {/* KPI strip */}
40
45
  <div className={styles.kpiRow}>
41
- <div className={styles.kpi}>
46
+ <div className={[styles.kpi, styles.kpiGrow].join(' ')}>
42
47
  <div className={styles.ico}></div>
43
48
  <div className={styles.meta}><div className={styles.num}></div><div className={styles.label}></div></div>
44
49
  </div>
@@ -70,7 +75,13 @@ export default function OpenRegisterMock({ sidebar = null }) {
70
75
  <div className={styles.panel}>
71
76
  <div className={styles.head}><div className={styles.title}></div></div>
72
77
  <div className={styles.stack}>
73
- {['b','d','c','a'].map((cls, i) => (
78
+ {/* The freshly-written object row: lands with a slide
79
+ when the loop fires. Present in static frames. */}
80
+ <div className={[styles.item, styles.newObj].join(' ')}>
81
+ <div className={[styles.av, styles.d].join(' ')}></div>
82
+ <div className={styles.lines}><div className={styles.l1}></div></div>
83
+ </div>
84
+ {['b','d','c'].map((cls, i) => (
74
85
  <div key={i} className={styles.item}>
75
86
  <div className={[styles.av, styles[cls]].join(' ')}></div>
76
87
  <div className={styles.lines}><div className={styles.l1}></div></div>