@conduction/docusaurus-preset 3.28.0 → 3.31.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 +4 -4
- package/src/components/AppMock/AppMock.jsx +16 -0
- package/src/components/AppMock/variants/AppVersionsMock.jsx +83 -0
- package/src/components/AppMock/variants/DoriathMock.jsx +79 -0
- package/src/components/AppMock/variants/HermiqMock.jsx +71 -0
- package/src/components/AppMock/variants/HrmqMock.jsx +77 -0
- package/src/components/AppMock/variants/PlanixMock.jsx +80 -0
- package/src/components/AppMock/variants/PortaliqMock.jsx +63 -0
- package/src/components/AppMock/variants/ScholiqMock.jsx +74 -0
- package/src/components/AppMock/variants/ShillinqMock.jsx +90 -0
- package/src/components/CookieCli/CookieCli.jsx +197 -24
- package/src/components/CookieCli/CookieCli.module.css +139 -1
- package/src/components/CookieCli/shell.js +161 -0
- package/src/components/CookieCli/spaceInvaders.js +359 -0
- package/src/components/CookieCli/spaceInvaders.test.js +112 -0
- package/src/data/app-glyphs.json +4 -0
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conduction/docusaurus-preset",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.31.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepack": "node scripts/prepack-bundle-css.js",
|
|
6
6
|
"test": "node --test"
|
|
7
7
|
},
|
|
8
8
|
"bin": {
|
|
9
|
-
"validate-ai-baseline": "
|
|
9
|
+
"validate-ai-baseline": "bin/validate-ai-baseline.mjs"
|
|
10
10
|
},
|
|
11
11
|
"description": "Conduction brand preset for Docusaurus 3. Tokens, theme, navbar, footer, i18n config for nl/en/de/fr, and the React component library that powers conduction.nl and the Conduction product sites.",
|
|
12
12
|
"main": "src/index.js",
|
|
@@ -61,10 +61,10 @@
|
|
|
61
61
|
"homepage": "https://design-system.conduction.nl/",
|
|
62
62
|
"repository": {
|
|
63
63
|
"type": "git",
|
|
64
|
-
"url": "https://
|
|
64
|
+
"url": "git+https://github.com/ConductionNL/design-system.git",
|
|
65
65
|
"directory": "docusaurus-preset"
|
|
66
66
|
},
|
|
67
67
|
"bugs": {
|
|
68
|
-
"url": "https://
|
|
68
|
+
"url": "https://github.com/ConductionNL/design-system/issues"
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -51,6 +51,14 @@ import OpenWooMock from './variants/OpenWooMock.jsx';
|
|
|
51
51
|
import PipelinQMock from './variants/PipelinQMock.jsx';
|
|
52
52
|
import SoftwareCatalogMock from './variants/SoftwareCatalogMock.jsx';
|
|
53
53
|
import ZaakAfhandelAppMock from './variants/ZaakAfhandelAppMock.jsx';
|
|
54
|
+
import HermiqMock from './variants/HermiqMock.jsx';
|
|
55
|
+
import PortaliqMock from './variants/PortaliqMock.jsx';
|
|
56
|
+
import ScholiqMock from './variants/ScholiqMock.jsx';
|
|
57
|
+
import ShillinqMock from './variants/ShillinqMock.jsx';
|
|
58
|
+
import DoriathMock from './variants/DoriathMock.jsx';
|
|
59
|
+
import PlanixMock from './variants/PlanixMock.jsx';
|
|
60
|
+
import HrmqMock from './variants/HrmqMock.jsx';
|
|
61
|
+
import AppVersionsMock from './variants/AppVersionsMock.jsx';
|
|
54
62
|
|
|
55
63
|
const VARIANTS = {
|
|
56
64
|
launchpad: {Component: LaunchPadMock, label: 'LaunchPad'},
|
|
@@ -70,6 +78,14 @@ const VARIANTS = {
|
|
|
70
78
|
pipelinq: {Component: PipelinQMock, label: 'PipelinQ'},
|
|
71
79
|
softwarecatalog: {Component: SoftwareCatalogMock, label: 'SoftwareCatalog'},
|
|
72
80
|
zaakafhandelapp: {Component: ZaakAfhandelAppMock, label: 'ZaakAfhandelApp'},
|
|
81
|
+
hermiq: {Component: HermiqMock, label: 'Hermiq'},
|
|
82
|
+
portaliq: {Component: PortaliqMock, label: 'Portaliq'},
|
|
83
|
+
scholiq: {Component: ScholiqMock, label: 'Scholiq'},
|
|
84
|
+
shillinq: {Component: ShillinqMock, label: 'Shillinq'},
|
|
85
|
+
doriath: {Component: DoriathMock, label: 'Doriath'},
|
|
86
|
+
planix: {Component: PlanixMock, label: 'Planix'},
|
|
87
|
+
hrmq: {Component: HrmqMock, label: 'HRMQ'},
|
|
88
|
+
'app-versions': {Component: AppVersionsMock, label: 'App Versions'},
|
|
73
89
|
};
|
|
74
90
|
|
|
75
91
|
export default function AppMock({app, size = 'md', sidebar = null, caption = false, className}) {
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Versions abstract — fleet version dashboard.
|
|
3
|
+
*
|
|
4
|
+
* Inferred from the app role (tracking installed app versions across
|
|
5
|
+
* a workspace): a KPI strip over an app list — app hex, name, version
|
|
6
|
+
* chip, and a status dot column where mint = up to date and
|
|
7
|
+
* terracotta = an update is waiting. Tone: workspace-blue — this is
|
|
8
|
+
* about the workspace itself.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import styles from '../AppMock.module.css';
|
|
13
|
+
|
|
14
|
+
const APPS = [
|
|
15
|
+
{upToDate: true},
|
|
16
|
+
{upToDate: true},
|
|
17
|
+
{upToDate: false, newChip: true},
|
|
18
|
+
{upToDate: true},
|
|
19
|
+
{upToDate: false, newChip: true},
|
|
20
|
+
{upToDate: true},
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export default function AppVersionsMock() {
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
<div className={styles.topbar}>
|
|
27
|
+
<div className={styles.logo}></div>
|
|
28
|
+
{Array.from({length: 14}).map((_, i) => <div key={i} className={styles.icon}></div>)}
|
|
29
|
+
<div className={styles.spacer}></div>
|
|
30
|
+
<div className={styles.bell}></div>
|
|
31
|
+
<div className={styles.avatar}></div>
|
|
32
|
+
</div>
|
|
33
|
+
<div className={[styles.body, styles.decidesk].filter(Boolean).join(' ')}>
|
|
34
|
+
<div className={styles.nav}>
|
|
35
|
+
<div className={styles.navHead}><div className={styles.h}></div><div className={styles.l}></div></div>
|
|
36
|
+
{[true, false, false].map((active, i) => (
|
|
37
|
+
<div key={i} className={[styles.item, active && styles.active].filter(Boolean).join(' ')}>
|
|
38
|
+
<div className={styles.ico}></div>
|
|
39
|
+
<div className={styles.l}></div>
|
|
40
|
+
</div>
|
|
41
|
+
))}
|
|
42
|
+
</div>
|
|
43
|
+
<div className={styles.col}>
|
|
44
|
+
<div className={styles.head}>
|
|
45
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '30%'}}></div>
|
|
46
|
+
<div className={styles.actions}>
|
|
47
|
+
<div className={styles.btn + ' ' + styles.ghost}></div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
<div className={styles.kpiRow}>
|
|
51
|
+
<div className={styles.kpi}>
|
|
52
|
+
<div className={styles.ico} style={{background: 'var(--c-workspaceblue-500)'}}></div>
|
|
53
|
+
<div className={styles.meta}><div className={styles.num}></div><div className={styles.label}></div></div>
|
|
54
|
+
</div>
|
|
55
|
+
<div className={styles.kpi}>
|
|
56
|
+
<div className={styles.ico}></div>
|
|
57
|
+
<div className={styles.meta}><div className={styles.num}></div><div className={styles.label}></div></div>
|
|
58
|
+
</div>
|
|
59
|
+
<div className={styles.kpi}>
|
|
60
|
+
<div className={styles.ico} style={{background: 'var(--c-terracotta-300)'}}></div>
|
|
61
|
+
<div className={styles.meta}><div className={styles.num}></div><div className={styles.label}></div></div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
{/* App rows: hex · name · version chip(s) · status dot */}
|
|
65
|
+
<div className={styles.panel} style={{flex: 1}}>
|
|
66
|
+
<div className={styles.head}><div className={styles.title}></div></div>
|
|
67
|
+
<div className={styles.stack}>
|
|
68
|
+
{APPS.map(({upToDate, newChip}, i) => (
|
|
69
|
+
<div key={i} className={styles.item}>
|
|
70
|
+
<div style={{width: 11, height: 13, clipPath: 'var(--hex-pointy-top)', background: upToDate ? 'var(--c-workspaceblue-500)' : 'var(--c-workspaceblue-300)', flexShrink: 0}}></div>
|
|
71
|
+
<div className={styles.lines}><div className={styles.l1}></div></div>
|
|
72
|
+
<div style={{width: 26, height: 9, borderRadius: 999, background: 'var(--c-cobalt-100)', flexShrink: 0}}></div>
|
|
73
|
+
{newChip && <div style={{width: 26, height: 9, borderRadius: 999, background: 'var(--c-workspaceblue-300)', flexShrink: 0}}></div>}
|
|
74
|
+
<div style={{width: 6, height: 6, borderRadius: '50%', background: upToDate ? 'var(--c-mint-500)' : 'var(--c-terracotta-500)', flexShrink: 0}}></div>
|
|
75
|
+
</div>
|
|
76
|
+
))}
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doriath abstract — secrets vault.
|
|
3
|
+
*
|
|
4
|
+
* Inferred from the app role (storing and sharing secrets): a list of
|
|
5
|
+
* locked entries — key hex, name, masked value rendered as a dot
|
|
6
|
+
* pattern — next to one unlocked detail card on a cobalt-900 surface
|
|
7
|
+
* with the revealed value in light. Tones: cobalt-900 for the vault
|
|
8
|
+
* interior, lavender for the keys.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import styles from '../AppMock.module.css';
|
|
13
|
+
|
|
14
|
+
export default function DoriathMock() {
|
|
15
|
+
const mask = (n) => (
|
|
16
|
+
<div style={{display: 'flex', gap: 2, flexShrink: 0}}>
|
|
17
|
+
{Array.from({length: n}).map((_, i) => (
|
|
18
|
+
<div key={i} style={{width: 3, height: 3, borderRadius: '50%', background: 'var(--c-cobalt-400)'}}></div>
|
|
19
|
+
))}
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
return (
|
|
23
|
+
<>
|
|
24
|
+
<div className={styles.topbar}>
|
|
25
|
+
<div className={styles.logo}></div>
|
|
26
|
+
{Array.from({length: 14}).map((_, i) => <div key={i} className={styles.icon}></div>)}
|
|
27
|
+
<div className={styles.spacer}></div>
|
|
28
|
+
<div className={styles.bell}></div>
|
|
29
|
+
<div className={styles.avatar}></div>
|
|
30
|
+
</div>
|
|
31
|
+
<div className={[styles.body, styles.decidesk].filter(Boolean).join(' ')}>
|
|
32
|
+
<div className={styles.nav}>
|
|
33
|
+
<div className={styles.navHead}><div className={styles.h}></div><div className={styles.l}></div></div>
|
|
34
|
+
{[true, false, false, false].map((active, i) => (
|
|
35
|
+
<div key={i} className={[styles.item, active && styles.active].filter(Boolean).join(' ')}>
|
|
36
|
+
<div className={styles.ico}></div>
|
|
37
|
+
<div className={styles.l}></div>
|
|
38
|
+
</div>
|
|
39
|
+
))}
|
|
40
|
+
</div>
|
|
41
|
+
<div className={styles.col}>
|
|
42
|
+
<div className={styles.head}>
|
|
43
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '25%'}}></div>
|
|
44
|
+
<div className={styles.actions}>
|
|
45
|
+
<div className={styles.btn + ' ' + styles.ghost}></div>
|
|
46
|
+
<div className={styles.btn}></div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
<div className={styles.panelRow} style={{gridTemplateColumns: '1.4fr 1fr'}}>
|
|
50
|
+
{/* Locked entries — key hex + name + masked value */}
|
|
51
|
+
<div className={styles.panel}>
|
|
52
|
+
<div className={styles.head}><div className={styles.title}></div></div>
|
|
53
|
+
<div className={styles.stack}>
|
|
54
|
+
{[6, 5, 7, 5, 6].map((dots, i) => (
|
|
55
|
+
<div key={i} className={styles.item}>
|
|
56
|
+
<div style={{width: 10, height: 11, clipPath: 'var(--hex-pointy-top)', background: 'var(--c-lavender-500)', flexShrink: 0}}></div>
|
|
57
|
+
<div className={styles.lines}><div className={styles.l1}></div></div>
|
|
58
|
+
{mask(dots)}
|
|
59
|
+
</div>
|
|
60
|
+
))}
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
{/* Unlocked entry — vault-dark card, value revealed */}
|
|
64
|
+
<div className={styles.panel} style={{background: 'var(--c-cobalt-900)', borderColor: 'var(--c-cobalt-900)'}}>
|
|
65
|
+
<div style={{display: 'flex', alignItems: 'center', gap: 5}}>
|
|
66
|
+
<div style={{width: 12, height: 14, clipPath: 'var(--hex-pointy-top)', background: 'var(--c-lavender-300)', flexShrink: 0}}></div>
|
|
67
|
+
<div style={{height: 6, width: '45%', background: 'var(--c-lavender-300)', borderRadius: 1}}></div>
|
|
68
|
+
</div>
|
|
69
|
+
<div style={{height: 3, width: '60%', background: 'rgba(255,255,255,0.25)', borderRadius: 1}}></div>
|
|
70
|
+
<div style={{height: 10, width: '85%', background: 'rgba(255,255,255,0.9)', borderRadius: 2}}></div>
|
|
71
|
+
<div style={{height: 3, width: '50%', background: 'rgba(255,255,255,0.25)', borderRadius: 1}}></div>
|
|
72
|
+
<div style={{height: 3, width: '70%', background: 'rgba(255,255,255,0.25)', borderRadius: 1}}></div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hermiq abstract — agent chat surface.
|
|
3
|
+
*
|
|
4
|
+
* Inferred from the app role (AI agents working inside the workspace):
|
|
5
|
+
* left rail lists the available agents, centre shows a conversation —
|
|
6
|
+
* user bubbles right, agent bubbles left — with a tool-call chip row
|
|
7
|
+
* between agent turns and a prompt input at the bottom. Tones:
|
|
8
|
+
* workspace-blue for the human side, mint for confirmed tool runs.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import styles from '../AppMock.module.css';
|
|
13
|
+
|
|
14
|
+
export default function HermiqMock() {
|
|
15
|
+
return (
|
|
16
|
+
<>
|
|
17
|
+
<div className={styles.topbar}>
|
|
18
|
+
<div className={styles.logo}></div>
|
|
19
|
+
{Array.from({length: 14}).map((_, i) => <div key={i} className={styles.icon}></div>)}
|
|
20
|
+
<div className={styles.spacer}></div>
|
|
21
|
+
<div className={styles.bell}></div>
|
|
22
|
+
<div className={styles.avatar}></div>
|
|
23
|
+
</div>
|
|
24
|
+
<div className={[styles.body, styles.decidesk].filter(Boolean).join(' ')}>
|
|
25
|
+
{/* Agent list rail */}
|
|
26
|
+
<div className={styles.nav}>
|
|
27
|
+
<div className={styles.navHead}><div className={styles.h}></div><div className={styles.l}></div></div>
|
|
28
|
+
{[true, false, false, false].map((active, i) => (
|
|
29
|
+
<div key={i} className={[styles.item, active && styles.active].filter(Boolean).join(' ')}>
|
|
30
|
+
<div className={styles.ico} style={{borderRadius: '50%'}}></div>
|
|
31
|
+
<div className={styles.l}></div>
|
|
32
|
+
</div>
|
|
33
|
+
))}
|
|
34
|
+
</div>
|
|
35
|
+
{/* Conversation */}
|
|
36
|
+
<div className={styles.col}>
|
|
37
|
+
<div className={styles.head}>
|
|
38
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '30%'}}></div>
|
|
39
|
+
<div className={styles.actions}>
|
|
40
|
+
<div className={styles.btn + ' ' + styles.ghost}></div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<div className={styles.panel} style={{flex: 1, gap: 8, justifyContent: 'flex-end'}}>
|
|
44
|
+
{/* User asks */}
|
|
45
|
+
<div style={{alignSelf: 'flex-end', width: '42%', height: 12, borderRadius: '8px 2px 8px 8px', background: 'var(--c-workspaceblue-300)'}}></div>
|
|
46
|
+
{/* Agent answers */}
|
|
47
|
+
<div style={{alignSelf: 'flex-start', width: '58%', height: 18, borderRadius: '2px 8px 8px 8px', background: 'var(--c-cobalt-50)', border: '1px solid var(--c-cobalt-100)'}}></div>
|
|
48
|
+
{/* Tool-call chip row — mint = tool run confirmed */}
|
|
49
|
+
<div style={{display: 'flex', alignItems: 'center', gap: 4}}>
|
|
50
|
+
<div className={styles.statusPill}>
|
|
51
|
+
<div className={styles.h}></div>
|
|
52
|
+
<div className={styles.t}></div>
|
|
53
|
+
</div>
|
|
54
|
+
<div style={{width: 34, height: 9, borderRadius: 999, background: 'var(--c-cobalt-100)'}}></div>
|
|
55
|
+
<div style={{width: 26, height: 9, borderRadius: 999, background: 'var(--c-cobalt-100)'}}></div>
|
|
56
|
+
</div>
|
|
57
|
+
{/* Agent continues with the tool result */}
|
|
58
|
+
<div style={{alignSelf: 'flex-start', width: '64%', height: 24, borderRadius: '2px 8px 8px 8px', background: 'var(--c-cobalt-50)', border: '1px solid var(--c-cobalt-100)'}}></div>
|
|
59
|
+
{/* User follows up */}
|
|
60
|
+
<div style={{alignSelf: 'flex-end', width: '34%', height: 12, borderRadius: '8px 2px 8px 8px', background: 'var(--c-workspaceblue-300)'}}></div>
|
|
61
|
+
</div>
|
|
62
|
+
{/* Prompt input */}
|
|
63
|
+
<div className={styles.actions} style={{alignItems: 'center'}}>
|
|
64
|
+
<div style={{flex: 1, height: 16, background: 'white', border: '1px solid var(--c-cobalt-200)', borderRadius: 8}}></div>
|
|
65
|
+
<div className={styles.btn} style={{width: 28}}></div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HRMQ abstract — people administration.
|
|
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.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import styles from '../AppMock.module.css';
|
|
11
|
+
|
|
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
|
+
];
|
|
19
|
+
|
|
20
|
+
export default function HrmqMock() {
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<div className={styles.topbar}>
|
|
24
|
+
<div className={styles.logo}></div>
|
|
25
|
+
{Array.from({length: 14}).map((_, i) => <div key={i} className={styles.icon}></div>)}
|
|
26
|
+
<div className={styles.spacer}></div>
|
|
27
|
+
<div className={styles.bell}></div>
|
|
28
|
+
<div className={styles.avatar}></div>
|
|
29
|
+
</div>
|
|
30
|
+
<div className={[styles.body, styles.decidesk].filter(Boolean).join(' ')}>
|
|
31
|
+
<div className={styles.nav}>
|
|
32
|
+
<div className={styles.navHead}><div className={styles.h}></div><div className={styles.l}></div></div>
|
|
33
|
+
{[true, false, false, false, false].map((active, i) => (
|
|
34
|
+
<div key={i} className={[styles.item, active && styles.active].filter(Boolean).join(' ')}>
|
|
35
|
+
<div className={styles.ico}></div>
|
|
36
|
+
<div className={styles.l}></div>
|
|
37
|
+
</div>
|
|
38
|
+
))}
|
|
39
|
+
</div>
|
|
40
|
+
<div className={styles.col}>
|
|
41
|
+
<div className={styles.head}>
|
|
42
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '25%'}}></div>
|
|
43
|
+
<div className={styles.actions}>
|
|
44
|
+
<div className={styles.btn}></div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
<div className={styles.panelRow} style={{gridTemplateColumns: '1.2fr 1fr'}}>
|
|
48
|
+
{/* People list — hex avatars */}
|
|
49
|
+
<div className={styles.panel}>
|
|
50
|
+
<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>
|
|
56
|
+
</div>
|
|
57
|
+
))}
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
{/* Leave-balance card — labelled bars */}
|
|
61
|
+
<div className={styles.panel}>
|
|
62
|
+
<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>
|
|
69
|
+
</div>
|
|
70
|
+
))}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Planix abstract — planning board.
|
|
3
|
+
*
|
|
4
|
+
* Inferred from the app role (scheduling people and work over time):
|
|
5
|
+
* a week grid of five day columns with placed planning blocks at
|
|
6
|
+
* varying heights, over a small capacity KPI strip. Tone: lavender —
|
|
7
|
+
* process and workflow.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import styles from '../AppMock.module.css';
|
|
12
|
+
|
|
13
|
+
/* Per day column: [height, shade] pairs; null = free slot spacer. */
|
|
14
|
+
const WEEK = [
|
|
15
|
+
[[14, 500], [10, 300]],
|
|
16
|
+
[[8, 300], [16, 500], [8, 300]],
|
|
17
|
+
[[12, 300], null, [10, 500]],
|
|
18
|
+
[[18, 500]],
|
|
19
|
+
[[8, 300], [8, 300]],
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
export default function PlanixMock() {
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
<div className={styles.topbar}>
|
|
26
|
+
<div className={styles.logo}></div>
|
|
27
|
+
{Array.from({length: 14}).map((_, i) => <div key={i} className={styles.icon}></div>)}
|
|
28
|
+
<div className={styles.spacer}></div>
|
|
29
|
+
<div className={styles.bell}></div>
|
|
30
|
+
<div className={styles.avatar}></div>
|
|
31
|
+
</div>
|
|
32
|
+
<div className={[styles.body, styles.decidesk].filter(Boolean).join(' ')}>
|
|
33
|
+
<div className={styles.nav}>
|
|
34
|
+
<div className={styles.navHead}><div className={styles.h}></div><div className={styles.l}></div></div>
|
|
35
|
+
{[true, false, false, false].map((active, i) => (
|
|
36
|
+
<div key={i} className={[styles.item, active && styles.active].filter(Boolean).join(' ')}>
|
|
37
|
+
<div className={styles.ico}></div>
|
|
38
|
+
<div className={styles.l}></div>
|
|
39
|
+
</div>
|
|
40
|
+
))}
|
|
41
|
+
</div>
|
|
42
|
+
<div className={styles.col}>
|
|
43
|
+
<div className={styles.head}>
|
|
44
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '25%'}}></div>
|
|
45
|
+
<div className={styles.actions}>
|
|
46
|
+
<div className={styles.btn + ' ' + styles.ghost}></div>
|
|
47
|
+
<div className={styles.btn}></div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
<div className={styles.kpiRow}>
|
|
51
|
+
<div className={[styles.kpi, styles.lavender].join(' ')}>
|
|
52
|
+
<div className={styles.ico}></div>
|
|
53
|
+
<div className={styles.meta}><div className={styles.num}></div><div className={styles.label}></div></div>
|
|
54
|
+
</div>
|
|
55
|
+
<div className={styles.kpi}>
|
|
56
|
+
<div className={styles.ico}></div>
|
|
57
|
+
<div className={styles.meta}><div className={styles.num}></div><div className={styles.label}></div></div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
{/* Week grid with placed planning blocks */}
|
|
61
|
+
<div className={styles.w} style={{flex: 1}}>
|
|
62
|
+
<div className={styles.wHead}>
|
|
63
|
+
<div className={styles.h}></div><div className={styles.t}></div>
|
|
64
|
+
</div>
|
|
65
|
+
<div style={{flex: 1, display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 4, minHeight: 60}}>
|
|
66
|
+
{WEEK.map((day, i) => (
|
|
67
|
+
<div key={i} style={{background: 'var(--c-cobalt-50)', borderRadius: 2, padding: 3, display: 'flex', flexDirection: 'column', gap: 2}}>
|
|
68
|
+
{day.map((block, j) => block
|
|
69
|
+
? <div key={j} style={{height: block[0], borderRadius: 1, background: `var(--c-lavender-${block[1]})`}}></div>
|
|
70
|
+
: <div key={j} style={{height: 8}}></div>
|
|
71
|
+
)}
|
|
72
|
+
</div>
|
|
73
|
+
))}
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portaliq abstract — external portal, seen from the visitor's side.
|
|
3
|
+
*
|
|
4
|
+
* Inferred from the app role (public-facing portals on top of the
|
|
5
|
+
* workspace): a slim public header instead of the full Nextcloud icon
|
|
6
|
+
* row, then a submission form card next to a message inbox list. No
|
|
7
|
+
* left nav — the visitor gets one page, not an admin surface. Tones:
|
|
8
|
+
* cobalt for the frame, mint for the delivered/confirmed states.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import styles from '../AppMock.module.css';
|
|
13
|
+
|
|
14
|
+
export default function PortaliqMock() {
|
|
15
|
+
return (
|
|
16
|
+
<>
|
|
17
|
+
{/* Public header: logo + a few page links, no app-icon strip */}
|
|
18
|
+
<div className={styles.topbar}>
|
|
19
|
+
<div className={styles.logo}></div>
|
|
20
|
+
<div className={styles.spacer}></div>
|
|
21
|
+
{Array.from({length: 3}).map((_, i) => <div key={i} className={styles.icon}></div>)}
|
|
22
|
+
<div className={styles.avatar}></div>
|
|
23
|
+
</div>
|
|
24
|
+
<div className={[styles.body, styles.decidesk].filter(Boolean).join(' ')}>
|
|
25
|
+
<div className={styles.col}>
|
|
26
|
+
{/* Portal masthead */}
|
|
27
|
+
<div className={styles.head}>
|
|
28
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '35%'}}></div>
|
|
29
|
+
<div className={styles.statusPill}>
|
|
30
|
+
<div className={styles.h}></div>
|
|
31
|
+
<div className={styles.t}></div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
<div className={styles.panelRow} style={{gridTemplateColumns: '1.2fr 1fr'}}>
|
|
35
|
+
{/* Submission form card */}
|
|
36
|
+
<div className={styles.panel}>
|
|
37
|
+
<div className={styles.head}><div className={styles.title}></div></div>
|
|
38
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '25%', height: 4}}></div>
|
|
39
|
+
<div style={{height: 14, background: 'white', border: '1px solid var(--c-cobalt-200)', borderRadius: 3}}></div>
|
|
40
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '30%', height: 4}}></div>
|
|
41
|
+
<div style={{height: 14, background: 'white', border: '1px solid var(--c-cobalt-200)', borderRadius: 3}}></div>
|
|
42
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '20%', height: 4}}></div>
|
|
43
|
+
<div style={{height: 26, background: 'white', border: '1px solid var(--c-cobalt-200)', borderRadius: 3}}></div>
|
|
44
|
+
<div className={styles.actions} style={{justifyContent: 'flex-end', marginTop: 2}}>
|
|
45
|
+
<div className={styles.btn}></div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
{/* Message inbox list */}
|
|
49
|
+
<div className={[styles.panel, styles['w-mail']].join(' ')}>
|
|
50
|
+
<div className={styles.head}><div className={styles.title}></div></div>
|
|
51
|
+
<div className={styles.list}>
|
|
52
|
+
<div className={styles.item}><div className={styles.av}></div><div className={styles.lines}><div className={styles.l1}></div><div className={styles.l2}></div></div></div>
|
|
53
|
+
<div className={styles.item}><div className={styles.av}></div><div className={styles.lines}><div className={styles.l1}></div><div className={styles.l2}></div></div></div>
|
|
54
|
+
<div className={styles.item}><div className={styles.av}></div><div className={styles.lines}><div className={styles.l1}></div><div className={styles.l2}></div></div></div>
|
|
55
|
+
<div className={styles.item}><div className={styles.av}></div><div className={styles.lines}><div className={styles.l1}></div><div className={styles.l2}></div></div></div>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scholiq abstract — learning environment.
|
|
3
|
+
*
|
|
4
|
+
* Inferred from the app role (courses, lessons, credentials): centre
|
|
5
|
+
* shows a course-card grid, each card carrying a progress bar, with a
|
|
6
|
+
* credential chip on the completed course. Left nav for courses /
|
|
7
|
+
* lessons / learners / certificates. Tone: forest — data you can
|
|
8
|
+
* trust a diploma to.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import styles from '../AppMock.module.css';
|
|
13
|
+
|
|
14
|
+
const PROGRESS = [
|
|
15
|
+
{ico: 'b', fill: '100%', done: true},
|
|
16
|
+
{ico: 'b', fill: '65%'},
|
|
17
|
+
{ico: null, fill: '40%'},
|
|
18
|
+
{ico: 'b', fill: '80%'},
|
|
19
|
+
{ico: 'e', fill: '25%'},
|
|
20
|
+
{ico: 'b', fill: '10%'},
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export default function ScholiqMock() {
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
<div className={styles.topbar}>
|
|
27
|
+
<div className={styles.logo}></div>
|
|
28
|
+
{Array.from({length: 14}).map((_, i) => <div key={i} className={styles.icon}></div>)}
|
|
29
|
+
<div className={styles.spacer}></div>
|
|
30
|
+
<div className={styles.bell}></div>
|
|
31
|
+
<div className={styles.avatar}></div>
|
|
32
|
+
</div>
|
|
33
|
+
<div className={[styles.body, styles.opencatalogi].filter(Boolean).join(' ')}>
|
|
34
|
+
<div className={styles.nav}>
|
|
35
|
+
<div className={styles.navHead}><div className={styles.h}></div><div className={styles.l}></div></div>
|
|
36
|
+
{[true, false, false, false].map((active, i) => (
|
|
37
|
+
<div key={i} className={[styles.item, active && styles.active].filter(Boolean).join(' ')}>
|
|
38
|
+
<div className={styles.ico}></div>
|
|
39
|
+
<div className={styles.l}></div>
|
|
40
|
+
</div>
|
|
41
|
+
))}
|
|
42
|
+
</div>
|
|
43
|
+
<div className={styles.col}>
|
|
44
|
+
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 6}}>
|
|
45
|
+
<div className={styles.row + ' ' + styles.head} style={{width: '30%'}}></div>
|
|
46
|
+
<div className={styles.actions}>
|
|
47
|
+
<div className={styles.btn}></div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
{/* Course cards with progress bars */}
|
|
51
|
+
<div className={styles.grid}>
|
|
52
|
+
{PROGRESS.map(({ico, fill, done}, i) => (
|
|
53
|
+
<div key={i} className={[styles.card, ico && styles[ico]].filter(Boolean).join(' ')}>
|
|
54
|
+
<div className={styles.ico}></div>
|
|
55
|
+
<div className={styles.row}></div>
|
|
56
|
+
<div className={styles.row + ' ' + styles.short}></div>
|
|
57
|
+
<div style={{height: 4, background: 'var(--c-cobalt-100)', borderRadius: 2}}>
|
|
58
|
+
<div style={{width: fill, height: 4, background: 'var(--c-forest-500)', borderRadius: 2}}></div>
|
|
59
|
+
</div>
|
|
60
|
+
{done && (
|
|
61
|
+
/* Credential chip — course completed, certificate issued */
|
|
62
|
+
<div style={{display: 'inline-flex', alignItems: 'center', gap: 3, padding: '2px 6px', borderRadius: 999, background: 'var(--c-forest-300)', alignSelf: 'flex-start'}}>
|
|
63
|
+
<div style={{width: 6, height: 7, clipPath: 'var(--hex-pointy-top)', background: 'var(--c-forest-500)'}}></div>
|
|
64
|
+
<div style={{height: 3, width: 22, background: 'var(--c-forest-500)', borderRadius: 1}}></div>
|
|
65
|
+
</div>
|
|
66
|
+
)}
|
|
67
|
+
</div>
|
|
68
|
+
))}
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</>
|
|
73
|
+
);
|
|
74
|
+
}
|