@neuravision/construct 2.0.3 → 2.1.2
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/CHANGELOG.md +318 -0
- package/README.md +158 -149
- package/behaviors/combobox.js +486 -0
- package/behaviors/drawer.js +18 -0
- package/behaviors/dropdown.js +310 -0
- package/behaviors/index.d.ts +335 -0
- package/behaviors/index.js +9 -0
- package/behaviors/internal/dialog-controller.js +421 -0
- package/behaviors/internal/dom.js +408 -0
- package/behaviors/internal/overlay.js +241 -0
- package/behaviors/internal/popup-layer.js +190 -0
- package/behaviors/modal.js +17 -0
- package/behaviors/popover.js +278 -0
- package/behaviors/select-menu.js +344 -0
- package/behaviors/tabs.js +241 -0
- package/behaviors/toggle-group.js +266 -0
- package/behaviors/tooltip.js +257 -0
- package/components/README.md +319 -83
- package/components/_shared.css +22 -10
- package/components/_shell-shared.css +20 -4
- package/components/accordion.css +8 -0
- package/components/app-shell-v2.css +28 -14
- package/components/app-shell.css +30 -14
- package/components/badge.css +15 -0
- package/components/banner.css +32 -1
- package/components/button.css +103 -15
- package/components/card.css +67 -8
- package/components/chart.css +26 -0
- package/components/checkbox.css +35 -2
- package/components/chip.css +30 -2
- package/components/combobox.css +21 -0
- package/components/datepicker.css +58 -9
- package/components/datum.css +277 -0
- package/components/dropdown.css +23 -3
- package/components/field.css +6 -4
- package/components/file-upload.css +1 -1
- package/components/index.css +5 -0
- package/components/list.css +28 -2
- package/components/meter.css +182 -0
- package/components/navbar.css +102 -4
- package/components/pagination.css +18 -0
- package/components/progress-bar.css +22 -1
- package/components/select-menu.css +8 -0
- package/components/select.css +8 -0
- package/components/sidebar.css +15 -2
- package/components/skip-link.css +6 -2
- package/components/slider.css +7 -1
- package/components/status.css +107 -0
- package/components/switch.css +66 -5
- package/components/table.css +53 -4
- package/components/tabs.css +55 -3
- package/components/toast.css +10 -1
- package/components/toggle-group.css +16 -5
- package/components/toolbar.css +17 -1
- package/components/tooltip.css +4 -0
- package/components/tree.css +30 -0
- package/docs/architecture.md +79 -0
- package/docs/behaviors.md +122 -0
- package/docs/fonts.md +70 -0
- package/docs/governance.md +85 -0
- package/docs/guidelines.md +72 -25
- package/examples/react/README.md +20 -0
- package/examples/react/SettingsModal.jsx +66 -0
- package/examples/react/construct.css +5 -0
- package/fonts.css +10 -0
- package/foundations.css +14 -1
- package/package.json +76 -21
- package/schemas/components.schema.json +122 -0
- package/schemas/examples/theme.example.json +27 -0
- package/schemas/primitives.schema.json +135 -0
- package/schemas/semantic.schema.json +224 -0
- package/schemas/theme.schema.json +63 -0
- package/scripts/build-tokens.mjs +1499 -0
- package/scripts/construct-theme.mjs +43 -0
- package/scripts/validate-tokens.mjs +25 -0
- package/standalone/accordion.css +3 -0
- package/standalone/alert.css +3 -0
- package/standalone/app-shell-v2.css +4 -0
- package/standalone/app-shell.css +4 -0
- package/standalone/avatar.css +3 -0
- package/standalone/badge.css +3 -0
- package/standalone/banner.css +3 -0
- package/standalone/breadcrumbs.css +3 -0
- package/standalone/button.css +3 -0
- package/standalone/card.css +3 -0
- package/standalone/chart.css +3 -0
- package/standalone/checkbox.css +3 -0
- package/standalone/chip.css +3 -0
- package/standalone/combobox.css +3 -0
- package/standalone/core.css +4 -0
- package/standalone/data-table.css +3 -0
- package/standalone/datepicker.css +3 -0
- package/standalone/datum.css +3 -0
- package/standalone/divider.css +3 -0
- package/standalone/drawer.css +3 -0
- package/standalone/dropdown.css +3 -0
- package/standalone/empty-state.css +3 -0
- package/standalone/field.css +3 -0
- package/standalone/file-upload.css +3 -0
- package/standalone/icon.css +3 -0
- package/standalone/input.css +3 -0
- package/standalone/list.css +3 -0
- package/standalone/meter.css +3 -0
- package/standalone/modal.css +3 -0
- package/standalone/navbar.css +3 -0
- package/standalone/pagination.css +3 -0
- package/standalone/popover.css +3 -0
- package/standalone/progress-bar.css +3 -0
- package/standalone/select-menu.css +3 -0
- package/standalone/select.css +3 -0
- package/standalone/sidebar.css +3 -0
- package/standalone/skeleton.css +3 -0
- package/standalone/skip-link.css +3 -0
- package/standalone/slider.css +3 -0
- package/standalone/spinner.css +3 -0
- package/standalone/status.css +3 -0
- package/standalone/switch.css +3 -0
- package/standalone/table.css +3 -0
- package/standalone/tabs.css +3 -0
- package/standalone/textarea.css +3 -0
- package/standalone/toast.css +3 -0
- package/standalone/toggle-group.css +3 -0
- package/standalone/toolbar.css +3 -0
- package/standalone/tooltip.css +3 -0
- package/standalone/tree.css +3 -0
- package/themes/README.md +37 -0
- package/themes/walnut.theme.json +106 -0
- package/tokens/README.md +135 -123
- package/tokens/components.json +64 -0
- package/tokens/primitives.json +268 -0
- package/tokens/semantic.dark.json +94 -0
- package/tokens/semantic.high-contrast-dark.json +94 -0
- package/tokens/semantic.high-contrast.json +94 -0
- package/tokens/semantic.light.json +179 -0
- package/tokens/tokens.css +960 -58
- package/tokens/tokens.js +729 -120
- package/tokens/tokens.json +1158 -116
- package/tokens/tokens.ts +729 -120
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import process from 'node:process';
|
|
5
|
+
|
|
6
|
+
import { buildTokens, parseArgs } from './build-tokens.mjs';
|
|
7
|
+
|
|
8
|
+
const help = [
|
|
9
|
+
'Usage: construct-theme --theme <file> [options]',
|
|
10
|
+
'',
|
|
11
|
+
'Builds Construct token outputs with one or more validated product themes.',
|
|
12
|
+
'',
|
|
13
|
+
'Options:',
|
|
14
|
+
' --theme <file> custom theme input; repeat to include more themes',
|
|
15
|
+
' --out-dir <directory> output directory (default: ./construct-theme)',
|
|
16
|
+
' --check fail when the output directory is not up to date',
|
|
17
|
+
' --validate-only validate without writing output',
|
|
18
|
+
' --report-contrast print every measured contrast ratio',
|
|
19
|
+
' -h, --help show this help',
|
|
20
|
+
].join('\n');
|
|
21
|
+
|
|
22
|
+
const hasOption = (args, name) =>
|
|
23
|
+
args.includes(name) || args.some((argument) => argument.startsWith(`${name}=`));
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const args = process.argv.slice(2);
|
|
27
|
+
const options = parseArgs(args);
|
|
28
|
+
|
|
29
|
+
if (options.help) {
|
|
30
|
+
console.log(help);
|
|
31
|
+
} else {
|
|
32
|
+
if (!options.themes.length) {
|
|
33
|
+
throw new Error('construct-theme requires at least one --theme <file> input.');
|
|
34
|
+
}
|
|
35
|
+
if (!hasOption(args, '--out-dir')) {
|
|
36
|
+
options.outDir = path.resolve(process.cwd(), 'construct-theme');
|
|
37
|
+
}
|
|
38
|
+
buildTokens(options);
|
|
39
|
+
}
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error(error.message);
|
|
42
|
+
process.exitCode = 1;
|
|
43
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import { buildTokens, parseArgs } from './build-tokens.mjs';
|
|
3
|
+
|
|
4
|
+
try {
|
|
5
|
+
const forwardedArgs = process.argv.slice(2);
|
|
6
|
+
if (forwardedArgs.includes('--check')) {
|
|
7
|
+
throw new Error('validate-tokens.mjs does not accept --check; use build-tokens.mjs --check.');
|
|
8
|
+
}
|
|
9
|
+
const options = parseArgs(['--validate-only', ...forwardedArgs]);
|
|
10
|
+
if (options.help) {
|
|
11
|
+
console.log(
|
|
12
|
+
[
|
|
13
|
+
'Usage: node scripts/validate-tokens.mjs [--theme <file>] [--report-contrast]',
|
|
14
|
+
'',
|
|
15
|
+
'Validates token schemas, layer references, theme completeness, unknown',
|
|
16
|
+
'overrides, and WCAG contrast pairs without writing generated files.',
|
|
17
|
+
].join('\n')
|
|
18
|
+
);
|
|
19
|
+
} else {
|
|
20
|
+
buildTokens(options);
|
|
21
|
+
}
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.error(error.message);
|
|
24
|
+
process.exitCode = 1;
|
|
25
|
+
}
|
package/themes/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Preset themes
|
|
2
|
+
|
|
3
|
+
Preset themes are validated, ready-to-use theme inputs shipped with the package. Unlike the
|
|
4
|
+
built-in themes (`light`, `dark`, `high-contrast`), presets are **not** compiled into
|
|
5
|
+
`tokens/tokens.css` — they are brand skins rather than modes, have no system-preference
|
|
6
|
+
mapping, and add no CSS payload for consumers that do not use them. A product opts in by
|
|
7
|
+
compiling the preset through the `construct-theme` CLI:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx construct-theme \
|
|
11
|
+
--theme node_modules/@neuravision/construct/themes/walnut.theme.json \
|
|
12
|
+
--out-dir ./src/generated/construct
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then activate it like any theme scope:
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<html data-theme="walnut"> … </html>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Products may also copy a preset as the starting point for their own theme and adjust
|
|
22
|
+
individual tokens; the CLI re-validates every override, including the contrast gates.
|
|
23
|
+
|
|
24
|
+
## Available presets
|
|
25
|
+
|
|
26
|
+
| Preset | Extends | Character |
|
|
27
|
+
|--------|---------|-----------|
|
|
28
|
+
| `walnut` | `light` | Warm ivory surfaces, walnut-brown brand color, wood-toned accents. Body text meets WCAG AAA (≥ 7:1) on all surfaces, enforced by `contrast` gates in the theme file. |
|
|
29
|
+
|
|
30
|
+
## Bar for adding a preset
|
|
31
|
+
|
|
32
|
+
- Must validate against `schemas/theme.schema.json` and pass every default contrast pair
|
|
33
|
+
(`npm run themes:validate` wires this into `npm run check`).
|
|
34
|
+
- Must declare its own `contrast` entries for any token the preset repurposes
|
|
35
|
+
(e.g. brand color used as text) and for stricter targets it claims (e.g. AAA body text).
|
|
36
|
+
- Palette, radius, and shadow decisions only — no font-family or type-scale overrides, so
|
|
37
|
+
presets compose with any product typography.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../schemas/theme.schema.json",
|
|
3
|
+
"name": "walnut",
|
|
4
|
+
"extends": "light",
|
|
5
|
+
"semantic": {
|
|
6
|
+
"color": {
|
|
7
|
+
"brand": {
|
|
8
|
+
"primary": "#6D4E33",
|
|
9
|
+
"primaryHover": "#5C4128",
|
|
10
|
+
"primaryActive": "#4C351F",
|
|
11
|
+
"accent": "#B0835E",
|
|
12
|
+
"accentHover": "#C2996F",
|
|
13
|
+
"accentActive": "#CBA57E",
|
|
14
|
+
"accentStrong": "#9F5210",
|
|
15
|
+
"onAccent": "#2A2014"
|
|
16
|
+
},
|
|
17
|
+
"text": {
|
|
18
|
+
"primary": "#2A2014",
|
|
19
|
+
"secondary": "#55432C",
|
|
20
|
+
"muted": "#6B573C",
|
|
21
|
+
"inverse": "#FFFFFF",
|
|
22
|
+
"onPrimary": "#FFFFFF"
|
|
23
|
+
},
|
|
24
|
+
"background": {
|
|
25
|
+
"canvas": "#FAF6ED",
|
|
26
|
+
"surface": "#F2EBDC",
|
|
27
|
+
"elevated": "#FFFFFF",
|
|
28
|
+
"muted": "#E9E0CC",
|
|
29
|
+
"subtle": "#F2EBDC"
|
|
30
|
+
},
|
|
31
|
+
"border": {
|
|
32
|
+
"subtle": "#E2D8C2",
|
|
33
|
+
"default": "#8A7256",
|
|
34
|
+
"strong": "#6D4E33",
|
|
35
|
+
"muted": "#E2D8C2"
|
|
36
|
+
},
|
|
37
|
+
"overlay": {
|
|
38
|
+
"scrim": "rgba(42, 32, 20, 0.55)"
|
|
39
|
+
},
|
|
40
|
+
"focus": {
|
|
41
|
+
"ring": "#9F5210"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"radius": {
|
|
45
|
+
"control": "7px",
|
|
46
|
+
"card": "10px",
|
|
47
|
+
"modal": "12px",
|
|
48
|
+
"pill": "999px"
|
|
49
|
+
},
|
|
50
|
+
"shadow": {
|
|
51
|
+
"card": "0 1px 2px rgba(58, 45, 26, 0.05), 0 2px 6px rgba(58, 45, 26, 0.06)",
|
|
52
|
+
"dropdown": "0 2px 6px rgba(58, 45, 26, 0.08), 0 8px 20px rgba(58, 45, 26, 0.12)",
|
|
53
|
+
"modal": "0 6px 16px rgba(58, 45, 26, 0.1), 0 24px 48px rgba(58, 45, 26, 0.18)"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"contrast": [
|
|
57
|
+
{
|
|
58
|
+
"name": "AAA: body text on canvas",
|
|
59
|
+
"foreground": "semantic.color.text.primary",
|
|
60
|
+
"background": "semantic.color.background.canvas",
|
|
61
|
+
"minRatio": 7
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "AAA: body text on surface",
|
|
65
|
+
"foreground": "semantic.color.text.primary",
|
|
66
|
+
"background": "semantic.color.background.surface",
|
|
67
|
+
"minRatio": 7
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "AAA: body text on elevated",
|
|
71
|
+
"foreground": "semantic.color.text.primary",
|
|
72
|
+
"background": "semantic.color.background.elevated",
|
|
73
|
+
"minRatio": 7
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "AAA: secondary text on canvas",
|
|
77
|
+
"foreground": "semantic.color.text.secondary",
|
|
78
|
+
"background": "semantic.color.background.canvas",
|
|
79
|
+
"minRatio": 7
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "brand primary used as text on canvas",
|
|
83
|
+
"foreground": "semantic.color.brand.primary",
|
|
84
|
+
"background": "semantic.color.background.canvas",
|
|
85
|
+
"minRatio": 4.5
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"name": "brand primary used as text on surface",
|
|
89
|
+
"foreground": "semantic.color.brand.primary",
|
|
90
|
+
"background": "semantic.color.background.surface",
|
|
91
|
+
"minRatio": 4.5
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "brand primary used as text on elevated",
|
|
95
|
+
"foreground": "semantic.color.brand.primary",
|
|
96
|
+
"background": "semantic.color.background.elevated",
|
|
97
|
+
"minRatio": 4.5
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "accent used as boundary on canvas",
|
|
101
|
+
"foreground": "semantic.color.brand.accent",
|
|
102
|
+
"background": "semantic.color.background.canvas",
|
|
103
|
+
"minRatio": 3
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|