@neuravision/construct 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +227 -0
  3. package/components/README.md +566 -0
  4. package/components/_keyframes.css +23 -0
  5. package/components/_shared.css +120 -0
  6. package/components/accordion.css +124 -0
  7. package/components/alert.css +67 -0
  8. package/components/avatar.css +127 -0
  9. package/components/badge.css +67 -0
  10. package/components/banner.css +247 -0
  11. package/components/breadcrumbs.css +152 -0
  12. package/components/button.css +145 -0
  13. package/components/card.css +76 -0
  14. package/components/checkbox.css +120 -0
  15. package/components/chip.css +361 -0
  16. package/components/combobox.css +385 -0
  17. package/components/components.css +2 -0
  18. package/components/data-table.css +93 -0
  19. package/components/datepicker.css +268 -0
  20. package/components/divider.css +73 -0
  21. package/components/drawer.css +167 -0
  22. package/components/dropdown.css +401 -0
  23. package/components/empty-state.css +97 -0
  24. package/components/field.css +42 -0
  25. package/components/file-upload.css +111 -0
  26. package/components/icon.css +31 -0
  27. package/components/index.css +49 -0
  28. package/components/input.css +64 -0
  29. package/components/list.css +474 -0
  30. package/components/modal.css +164 -0
  31. package/components/navbar.css +587 -0
  32. package/components/pagination.css +131 -0
  33. package/components/popover.css +231 -0
  34. package/components/progress-bar.css +56 -0
  35. package/components/select-menu.css +267 -0
  36. package/components/select.css +30 -0
  37. package/components/sidebar.css +183 -0
  38. package/components/skeleton.css +38 -0
  39. package/components/skip-link.css +38 -0
  40. package/components/slider.css +305 -0
  41. package/components/spinner.css +72 -0
  42. package/components/switch.css +82 -0
  43. package/components/table.css +139 -0
  44. package/components/tabs.css +147 -0
  45. package/components/textarea.css +16 -0
  46. package/components/toast.css +71 -0
  47. package/components/toggle-group.css +196 -0
  48. package/components/toolbar.css +222 -0
  49. package/components/tooltip.css +124 -0
  50. package/docs/guidelines.md +141 -0
  51. package/foundations.css +299 -0
  52. package/package.json +66 -0
  53. package/tokens/README.md +179 -0
  54. package/tokens/tokens.css +434 -0
  55. package/tokens/tokens.js +1188 -0
  56. package/tokens/tokens.json +810 -0
  57. package/tokens/tokens.ts +1188 -0
@@ -0,0 +1,299 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700&family=Source+Sans+3:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap');
2
+ @import './tokens/tokens.css';
3
+
4
+ :root {
5
+ color-scheme: var(--theme-color-scheme, light);
6
+ font-family: var(--font-family-text);
7
+ text-rendering: optimizeLegibility;
8
+ -webkit-font-smoothing: antialiased;
9
+ font-synthesis: none;
10
+ accent-color: var(--color-brand-accent);
11
+ }
12
+
13
+ *,
14
+ *::before,
15
+ *::after {
16
+ box-sizing: border-box;
17
+ }
18
+
19
+ html {
20
+ height: 100%;
21
+ text-size-adjust: 100%;
22
+ }
23
+
24
+ body {
25
+ min-height: 100%;
26
+ margin: 0;
27
+ background: var(--color-bg-canvas);
28
+ color: var(--color-text-primary);
29
+ font-family: var(--font-family-text);
30
+ font-size: var(--font-size-md);
31
+ line-height: var(--line-height-md);
32
+ }
33
+
34
+ main {
35
+ display: block;
36
+ }
37
+
38
+ img,
39
+ picture,
40
+ video,
41
+ canvas,
42
+ svg {
43
+ display: block;
44
+ max-width: 100%;
45
+ }
46
+
47
+ a {
48
+ color: var(--color-brand-primary);
49
+ text-decoration: underline;
50
+ text-decoration-thickness: 1px;
51
+ text-underline-offset: 0.15em;
52
+ }
53
+
54
+ a:hover {
55
+ color: var(--color-brand-primary-hover);
56
+ text-decoration-thickness: 2px;
57
+ }
58
+
59
+ a:active {
60
+ color: var(--color-brand-primary-active);
61
+ }
62
+
63
+ p {
64
+ margin: 0 0 var(--space-6);
65
+ }
66
+
67
+ small {
68
+ font-size: var(--font-size-sm);
69
+ color: var(--color-text-muted);
70
+ }
71
+
72
+ h1,
73
+ h2,
74
+ h3,
75
+ h4,
76
+ h5,
77
+ h6 {
78
+ margin: 0 0 var(--space-5);
79
+ color: var(--color-text-primary);
80
+ }
81
+
82
+ h1 {
83
+ font-family: var(--type-h1-font-family);
84
+ font-size: var(--type-h1-font-size);
85
+ line-height: var(--type-h1-line-height);
86
+ font-weight: var(--type-h1-font-weight);
87
+ letter-spacing: var(--type-h1-letter-spacing);
88
+ }
89
+
90
+ h2 {
91
+ font-family: var(--type-h2-font-family);
92
+ font-size: var(--type-h2-font-size);
93
+ line-height: var(--type-h2-line-height);
94
+ font-weight: var(--type-h2-font-weight);
95
+ letter-spacing: var(--type-h2-letter-spacing);
96
+ }
97
+
98
+ h3 {
99
+ font-family: var(--type-h3-font-family);
100
+ font-size: var(--type-h3-font-size);
101
+ line-height: var(--type-h3-line-height);
102
+ font-weight: var(--type-h3-font-weight);
103
+ letter-spacing: var(--type-h3-letter-spacing);
104
+ }
105
+
106
+ h4 {
107
+ font-family: var(--type-h4-font-family);
108
+ font-size: var(--type-h4-font-size);
109
+ line-height: var(--type-h4-line-height);
110
+ font-weight: var(--type-h4-font-weight);
111
+ letter-spacing: var(--type-h4-letter-spacing);
112
+ }
113
+
114
+ label {
115
+ font-family: var(--type-label-font-family);
116
+ font-size: var(--type-label-font-size);
117
+ line-height: var(--type-label-line-height);
118
+ font-weight: var(--type-label-font-weight);
119
+ letter-spacing: var(--type-label-letter-spacing);
120
+ }
121
+
122
+ code,
123
+ pre,
124
+ kbd,
125
+ samp {
126
+ font-family: var(--font-family-mono);
127
+ font-size: var(--font-size-sm);
128
+ }
129
+
130
+ pre {
131
+ margin: 0 0 var(--space-6);
132
+ padding: var(--space-6);
133
+ background: var(--color-bg-muted);
134
+ border-radius: var(--radius-md);
135
+ overflow: auto;
136
+ }
137
+
138
+ hr {
139
+ border: 0;
140
+ border-top: var(--border-thin) solid var(--color-border-subtle);
141
+ margin: var(--space-8) 0;
142
+ }
143
+
144
+ table {
145
+ width: 100%;
146
+ border-collapse: collapse;
147
+ }
148
+
149
+ th,
150
+ td {
151
+ padding: var(--space-4) var(--space-5);
152
+ text-align: left;
153
+ border-bottom: var(--border-thin) solid var(--color-border-subtle);
154
+ }
155
+
156
+ thead th {
157
+ font-weight: var(--font-weight-semibold);
158
+ color: var(--color-text-secondary);
159
+ }
160
+
161
+ button,
162
+ input,
163
+ select,
164
+ textarea {
165
+ font: inherit;
166
+ color: inherit;
167
+ }
168
+
169
+ textarea {
170
+ resize: vertical;
171
+ }
172
+
173
+ button {
174
+ cursor: pointer;
175
+ }
176
+
177
+ :disabled {
178
+ cursor: not-allowed;
179
+ opacity: var(--opacity-disabled);
180
+ }
181
+
182
+ :focus-visible {
183
+ outline: 3px solid var(--color-focus-ring);
184
+ outline-offset: 2px;
185
+ }
186
+
187
+ ::selection {
188
+ background: var(--color-brand-accent);
189
+ color: var(--color-text-inverse);
190
+ }
191
+
192
+ .ct-container {
193
+ width: min(100%, var(--container-lg));
194
+ margin-inline: auto;
195
+ padding-inline: clamp(var(--gutter-sm), 3vw, var(--gutter-lg));
196
+ }
197
+
198
+ .ct-grid {
199
+ display: grid;
200
+ gap: var(--grid-gap-md);
201
+ grid-template-columns: repeat(
202
+ auto-fit,
203
+ minmax(var(--ct-grid-min, 240px), 1fr)
204
+ );
205
+ }
206
+
207
+ .ct-stack > * + * {
208
+ margin-top: var(--ct-stack-space, var(--space-6));
209
+ }
210
+
211
+ .ct-cluster {
212
+ display: flex;
213
+ flex-wrap: wrap;
214
+ gap: var(--ct-cluster-gap, var(--space-4));
215
+ align-items: center;
216
+ }
217
+
218
+ .ct-card {
219
+ background: var(--color-bg-elevated);
220
+ border: var(--border-thin) solid var(--color-border-subtle);
221
+ border-radius: var(--radius-card);
222
+ box-shadow: var(--shadow-card);
223
+ padding: var(--space-7);
224
+ }
225
+
226
+ .ct-surface {
227
+ background: var(--color-bg-surface);
228
+ }
229
+
230
+ .ct-muted {
231
+ color: var(--color-text-muted);
232
+ }
233
+
234
+ .ct-text-center {
235
+ text-align: center;
236
+ }
237
+
238
+ .ct-w-100 {
239
+ width: 100%;
240
+ }
241
+
242
+ .ct-max-readable {
243
+ max-width: 65ch;
244
+ }
245
+
246
+ .ct-sr-only {
247
+ border: 0;
248
+ clip: rect(0 0 0 0);
249
+ height: 1px;
250
+ margin: -1px;
251
+ overflow: hidden;
252
+ padding: 0;
253
+ position: absolute;
254
+ width: 1px;
255
+ white-space: nowrap;
256
+ }
257
+
258
+ /* ============================================================
259
+ Visually Hidden
260
+ Hides content visually while keeping it accessible to screen
261
+ readers. Uses the modern clip-path technique with clip fallback.
262
+ ============================================================ */
263
+
264
+ .ct-visually-hidden {
265
+ border: 0;
266
+ clip: rect(0 0 0 0);
267
+ clip-path: inset(50%);
268
+ height: 1px;
269
+ margin: -1px;
270
+ overflow: hidden;
271
+ padding: 0;
272
+ position: absolute;
273
+ width: 1px;
274
+ white-space: nowrap;
275
+ }
276
+
277
+ .ct-visually-hidden--focusable:focus,
278
+ .ct-visually-hidden--focusable:focus-visible,
279
+ .ct-visually-hidden--focusable:active {
280
+ clip: auto;
281
+ clip-path: none;
282
+ height: auto;
283
+ margin: 0;
284
+ overflow: visible;
285
+ position: static;
286
+ width: auto;
287
+ white-space: normal;
288
+ }
289
+
290
+ @media (prefers-reduced-motion: reduce) {
291
+ *,
292
+ *::before,
293
+ *::after {
294
+ animation-duration: 0.01ms !important;
295
+ animation-iteration-count: 1 !important;
296
+ transition-duration: 0.01ms !important;
297
+ scroll-behavior: auto !important;
298
+ }
299
+ }
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@neuravision/construct",
3
+ "version": "1.1.0",
4
+ "description": "Construct Design System - Accessible, token-based design system for modern web applications",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/Samyssmile/construct.git"
9
+ },
10
+ "homepage": "https://samyssmile.github.io/construct",
11
+ "keywords": [
12
+ "design-system",
13
+ "design-tokens",
14
+ "accessibility",
15
+ "a11y",
16
+ "css",
17
+ "components"
18
+ ],
19
+ "type": "module",
20
+ "scripts": {
21
+ "build": "node scripts/build-tokens.mjs",
22
+ "check": "node scripts/build-tokens.mjs --check",
23
+ "storybook": "storybook dev -p 6006",
24
+ "storybook:build": "storybook build"
25
+ },
26
+ "exports": {
27
+ "./foundations.css": "./foundations.css",
28
+ "./components/components.css": "./components/components.css",
29
+ "./components/index.css": "./components/index.css",
30
+ "./components/*.css": "./components/*.css",
31
+ "./tokens/tokens.css": "./tokens/tokens.css",
32
+ "./tokens/tokens.json": "./tokens/tokens.json",
33
+ "./tokens/tokens": {
34
+ "types": "./tokens/tokens.ts",
35
+ "default": "./tokens/tokens.js"
36
+ },
37
+ "./tokens": {
38
+ "types": "./tokens/tokens.ts",
39
+ "default": "./tokens/tokens.js"
40
+ }
41
+ },
42
+ "files": [
43
+ "foundations.css",
44
+ "tokens/tokens.css",
45
+ "tokens/tokens.json",
46
+ "tokens/tokens.js",
47
+ "tokens/tokens.ts",
48
+ "tokens/README.md",
49
+ "docs/guidelines.md",
50
+ "components/*.css",
51
+ "components/README.md",
52
+ "README.md"
53
+ ],
54
+ "devDependencies": {
55
+ "@storybook/addon-a11y": "^10.2.3",
56
+ "@storybook/addon-docs": "^10.2.3",
57
+ "@storybook/addon-themes": "^10.2.3",
58
+ "@storybook/addon-vitest": "^10.2.3",
59
+ "@storybook/html-vite": "^10.2.3",
60
+ "@vitest/browser-playwright": "^4.0.18",
61
+ "@vitest/coverage-v8": "^4.0.18",
62
+ "playwright": "^1.58.1",
63
+ "storybook": "^10.2.3",
64
+ "vitest": "^4.0.18"
65
+ }
66
+ }
@@ -0,0 +1,179 @@
1
+ # Construct Design Tokens
2
+
3
+ Design tokens are the single source of truth for all design decisions in the Construct Design System. They provide consistent values for colors, typography, spacing, and more across all applications.
4
+
5
+ ## Design Direction
6
+
7
+ - **Enterprise-grade**: Clean, professional, high-trust aesthetic
8
+ - **Ocean primary**: Deep, authoritative blue for key actions
9
+ - **Teal accent**: Modern, clear accent for highlights
10
+ - **Slate neutrals**: Versatile grays for typography and surfaces
11
+
12
+ ## Files
13
+
14
+ - **`primitives.json`**: Raw values (color palettes, typography scale, spacing, radius, shadows, layout)
15
+ - **`semantic.light.json`**: Semantic mappings for light theme (brand, text, background, state colors)
16
+ - **`semantic.dark.json`**: Dark theme overrides (color + theme metadata)
17
+ - **`semantic.high-contrast.json`**: High-contrast theme overrides (color + theme metadata)
18
+ - **`tokens.css`**: Generated CSS Custom Properties (ready for import)
19
+ - **`tokens.json`**: Generated, resolved token values with units (for tooling)
20
+ - **`tokens.js`**: Generated JavaScript module for runtime imports
21
+ - **`tokens.ts`**: Generated TypeScript definitions and typed exports
22
+
23
+ ## Two-Tier Token System
24
+
25
+ ### Primitives
26
+ Raw design values that form the foundation:
27
+
28
+ ```json
29
+ {
30
+ "color": {
31
+ "ocean": {
32
+ "700": "#174C5D"
33
+ }
34
+ },
35
+ "space": {
36
+ "4": 8
37
+ }
38
+ }
39
+ ```
40
+
41
+ ### Semantic
42
+ Contextual tokens that reference primitives:
43
+
44
+ ```json
45
+ {
46
+ "color": {
47
+ "brand": {
48
+ "primary": "{color.ocean.700}"
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ This approach means:
55
+ - **Primitives** rarely change (your color palette)
56
+ - **Semantic** tokens can be remapped for themes without touching primitives
57
+ - Consistency is enforced automatically
58
+
59
+ ## Usage
60
+
61
+ ### CSS
62
+
63
+ Import the generated CSS file:
64
+
65
+ ```css
66
+ @import "@neuravision/construct/tokens/tokens.css";
67
+
68
+ body {
69
+ font-family: var(--font-family-body);
70
+ color: var(--color-text-primary);
71
+ background: var(--color-bg-canvas);
72
+ }
73
+
74
+ .button {
75
+ background: var(--color-brand-primary);
76
+ padding: var(--space-4) var(--space-6);
77
+ border-radius: var(--radius-control);
78
+ }
79
+ ```
80
+
81
+ ### Themes
82
+
83
+ Construct ships with light (default), dark, and high-contrast themes. The generated CSS includes theme overrides and system preference fallbacks.
84
+
85
+ ```html
86
+ <html data-theme="dark">
87
+ ...
88
+ </html>
89
+ ```
90
+
91
+ Available values:
92
+ - `light` (default)
93
+ - `dark`
94
+ - `high-contrast`
95
+
96
+ If no `data-theme` is set, the system preferences are respected:
97
+ - `prefers-color-scheme: dark` → dark theme
98
+ - `prefers-contrast: more` → high-contrast theme
99
+
100
+ ### TypeScript/JavaScript
101
+
102
+ Import the generated token module:
103
+
104
+ ```typescript
105
+ import { tokens, cssVars } from '@neuravision/construct/tokens/tokens';
106
+
107
+ // Use resolved values
108
+ console.log(tokens.semantic.color.brand.primary); // "#174C5D"
109
+
110
+ // Or use CSS variable references
111
+ console.log(cssVars.semantic.color.brand.primary); // "var(--color-brand-primary)"
112
+
113
+ // Access full theme maps
114
+ console.log(tokens.semanticThemes.dark.color.background.canvas);
115
+ ```
116
+
117
+ ## Building Tokens
118
+
119
+ The build script generates CSS, JSON, JavaScript, and TypeScript outputs from the source token files.
120
+
121
+ ### Run Build
122
+
123
+ From repository root:
124
+ ```bash
125
+ node design/scripts/build-tokens.mjs
126
+ ```
127
+
128
+ From `design/` directory:
129
+ ```bash
130
+ npm run build
131
+ ```
132
+
133
+ ### Check if Up-to-Date (CI)
134
+
135
+ Verify outputs match sources without rebuilding:
136
+
137
+ ```bash
138
+ npm run check
139
+ ```
140
+
141
+ This command exits with a non-zero code if outputs are outdated, making it perfect for CI/CD pipelines.
142
+
143
+ ## Token Naming Conventions
144
+
145
+ ### CSS Variables
146
+
147
+ Tokens are converted to kebab-case CSS variables:
148
+
149
+ - Primitives: `--color-ocean-700`, `--space-4`, `--radius-md`
150
+ - Semantic: `--color-brand-primary`, `--color-text-primary`, `--color-bg-canvas`
151
+
152
+ ### TypeScript
153
+
154
+ Tokens are available as nested objects with camelCase properties:
155
+
156
+ ```typescript
157
+ tokens.primitives.color.ocean[700]
158
+ tokens.semantic.color.brand.primary
159
+ cssVars.semantic.color.brand.primary
160
+ ```
161
+
162
+ ## Brand Guidance
163
+
164
+ - **Primary**: Use for key actions, primary buttons, and main navigation
165
+ - **Accent**: Use sparingly for highlights, special emphasis, and interactive elements
166
+ - **Backgrounds**: Prefer `surface` and `muted` for large content areas
167
+ - **Text**: Use `primary` for body text, `secondary` for less important text, `muted` for hints
168
+
169
+ ## Versioning
170
+
171
+ Tokens follow Semantic Versioning:
172
+
173
+ - **MAJOR**: Removing/renaming tokens or changing existing token values
174
+ - **MINOR**: Adding new tokens, scales, or semantic aliases
175
+ - **PATCH**: Documentation, build scripts, internal changes (no token value changes)
176
+
177
+ ---
178
+
179
+ **Construct** - Build accessible design constructs