@spaced-out/ui-design-system 0.5.21 → 0.5.23
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 +14 -0
- package/lib/components/Input/Input.d.ts +2 -0
- package/lib/components/Input/Input.d.ts.map +1 -1
- package/lib/components/Input/Input.js +79 -57
- package/lib/components/Input/Input.module.css +23 -0
- package/lib/components/SearchInput/SearchInput.d.ts +2 -0
- package/lib/components/SearchInput/SearchInput.d.ts.map +1 -1
- package/lib/components/SearchInput/SearchInput.js +3 -1
- package/lib/components/Typeahead/Typeahead.d.ts +1 -0
- package/lib/components/Typeahead/Typeahead.d.ts.map +1 -1
- package/lib/components/Typeahead/Typeahead.js +2 -0
- package/mcp/build-mcp-data.js +162 -8
- package/mcp/index.js +709 -1
- package/mcp/package.json +1 -1
- package/package.json +1 -1
package/mcp/index.js
CHANGED
|
@@ -51,6 +51,8 @@ console.error('✅ Loaded Genesis design system data');
|
|
|
51
51
|
console.error(` Version: ${designSystemData.metadata.version}`);
|
|
52
52
|
console.error(` Components: ${Object.keys(designSystemData.components).length}`);
|
|
53
53
|
console.error(` Hooks: ${Object.keys(designSystemData.hooks).length}`);
|
|
54
|
+
console.error(` Utils: ${Object.keys(designSystemData.utils || {}).length}`);
|
|
55
|
+
console.error(` Types: ${Object.keys(designSystemData.types || {}).length}`);
|
|
54
56
|
console.error(` Built: ${designSystemData.metadata.buildDate}`);
|
|
55
57
|
|
|
56
58
|
/**
|
|
@@ -67,6 +69,20 @@ function getAllHooks() {
|
|
|
67
69
|
return Object.keys(designSystemData.hooks).sort();
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Get all utils
|
|
74
|
+
*/
|
|
75
|
+
function getAllUtils() {
|
|
76
|
+
return Object.keys(designSystemData.utils || {}).sort();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get all types
|
|
81
|
+
*/
|
|
82
|
+
function getAllTypes() {
|
|
83
|
+
return Object.keys(designSystemData.types || {}).sort();
|
|
84
|
+
}
|
|
85
|
+
|
|
70
86
|
/**
|
|
71
87
|
* Get component details
|
|
72
88
|
*/
|
|
@@ -81,6 +97,20 @@ function getHookDetails(hookName) {
|
|
|
81
97
|
return designSystemData.hooks[hookName] || null;
|
|
82
98
|
}
|
|
83
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Get util details
|
|
102
|
+
*/
|
|
103
|
+
function getUtilDetails(utilName) {
|
|
104
|
+
return designSystemData.utils?.[utilName] || null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get type details
|
|
109
|
+
*/
|
|
110
|
+
function getTypeDetails(typeName) {
|
|
111
|
+
return designSystemData.types?.[typeName] || null;
|
|
112
|
+
}
|
|
113
|
+
|
|
84
114
|
/**
|
|
85
115
|
* Get all design tokens
|
|
86
116
|
*/
|
|
@@ -126,8 +156,35 @@ function searchComponents(query) {
|
|
|
126
156
|
function getCSSModuleGuidelines() {
|
|
127
157
|
return {
|
|
128
158
|
description: 'Comprehensive CSS Module guidelines and best practices for the Genesis Design System',
|
|
159
|
+
contextNote: {
|
|
160
|
+
critical: '⚠️ IMPORTANT: Patterns differ based on context',
|
|
161
|
+
insideDesignSystem: 'Use .module.css files with PascalCase naming and relative token imports',
|
|
162
|
+
usingDesignSystem: 'Use .css files (no .module) with kebab-case naming and @spaced-out/ui-design-system imports',
|
|
163
|
+
recommendation: 'Call get_css_module_import_patterns tool for detailed context-specific examples',
|
|
164
|
+
},
|
|
129
165
|
typescriptRequirement: '⚠️ CRITICAL: Use pure TypeScript only. NO Flow types (Flow.AbstractComponent). Use React.forwardRef<HTMLElement, Props> pattern.',
|
|
166
|
+
cssModuleImportPattern: {
|
|
167
|
+
critical: '🚨 MANDATORY: ALWAYS import CSS Modules as a default import with "css" as the variable name',
|
|
168
|
+
insideDesignSystem: 'import css from \'./ComponentName.module.css\';',
|
|
169
|
+
usingDesignSystem: 'import css from \'./component-name.css\';',
|
|
170
|
+
incorrect: [
|
|
171
|
+
'import \'./ComponentName.module.css\'; // ❌ WRONG - No side-effect imports',
|
|
172
|
+
'import * as css from \'./ComponentName.module.css\'; // ❌ WRONG - No namespace imports',
|
|
173
|
+
'import styles from \'./ComponentName.module.css\'; // ❌ WRONG - Must use "css" as variable name',
|
|
174
|
+
],
|
|
175
|
+
classNameUsage: {
|
|
176
|
+
correct: 'className={css.tableHeaderContent} // Use camelCase property access',
|
|
177
|
+
incorrect: [
|
|
178
|
+
'className="table-header-content" // ❌ WRONG - No string literals',
|
|
179
|
+
'className="tableHeaderContent" // ❌ WRONG - No string literals',
|
|
180
|
+
'className={\'table-header-content\'} // ❌ WRONG - No string literals in braces',
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
explanation: 'CSS Modules require a default import to access class names as properties. The variable MUST be named "css" for consistency across the codebase. Class names are accessed as camelCase properties (css.myClass) not as string literals.',
|
|
184
|
+
},
|
|
130
185
|
criticalRules: [
|
|
186
|
+
'🚨 MANDATORY: Import CSS Modules as: import css from \'./Component.module.css\'',
|
|
187
|
+
'🚨 MANDATORY: Use className={css.className} NOT className="class-name"',
|
|
131
188
|
'⚠️ ALWAYS use design tokens instead of hardcoded values',
|
|
132
189
|
'⚠️ Use BEM modifier pattern: .baseClass.modifier NOT .baseClass--modifier',
|
|
133
190
|
'⚠️ Use descendant selectors for child element styling: .container .childClass NOT :global() selectors',
|
|
@@ -231,6 +288,20 @@ function getCSSModuleGuidelines() {
|
|
|
231
288
|
},
|
|
232
289
|
realWorldExample: {
|
|
233
290
|
description: 'Complete example with state-based styling for multiple child elements',
|
|
291
|
+
importPattern: `// 🚨 MANDATORY: Import CSS Module as default with "css" variable name
|
|
292
|
+
import css from './ComponentName.module.css';
|
|
293
|
+
|
|
294
|
+
// Usage in JSX:
|
|
295
|
+
<div className={css.wrapper}>
|
|
296
|
+
<div className={css.header}>
|
|
297
|
+
<span className={css.title}>Title</span>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
|
|
301
|
+
// ❌ NEVER DO THIS:
|
|
302
|
+
// import './ComponentName.module.css';
|
|
303
|
+
// <div className="wrapper">
|
|
304
|
+
// <div className={'wrapper'}>`,
|
|
234
305
|
code: `@value (
|
|
235
306
|
colorBorderPrimary,
|
|
236
307
|
colorBackgroundTertiary,
|
|
@@ -295,6 +366,16 @@ function getCSSModuleGuidelines() {
|
|
|
295
366
|
}`,
|
|
296
367
|
},
|
|
297
368
|
commonMistakes: [
|
|
369
|
+
{
|
|
370
|
+
mistake: '🚨 CRITICAL: Incorrect CSS Module import or usage',
|
|
371
|
+
wrong: `import './Component.module.css'; // Side-effect import
|
|
372
|
+
import styles from './Component.module.css'; // Wrong variable name
|
|
373
|
+
<div className="wrapper"> // String literal
|
|
374
|
+
<div className={'wrapper'}> // String literal in braces`,
|
|
375
|
+
right: `import css from './Component.module.css'; // Default import with "css" variable
|
|
376
|
+
<div className={css.wrapper}> // Property access with camelCase`,
|
|
377
|
+
explanation: 'CSS Modules MUST be imported as default with variable name "css" and used via property access, never as string literals.',
|
|
378
|
+
},
|
|
298
379
|
{
|
|
299
380
|
mistake: 'Using hardcoded pixel values',
|
|
300
381
|
wrong: 'width: 58px; height: 78px; padding: 12px 16px;',
|
|
@@ -324,6 +405,346 @@ function getCSSModuleGuidelines() {
|
|
|
324
405
|
};
|
|
325
406
|
}
|
|
326
407
|
|
|
408
|
+
/**
|
|
409
|
+
* Get CSS Module import and usage patterns
|
|
410
|
+
*/
|
|
411
|
+
function getCSSModuleImportPatterns() {
|
|
412
|
+
return {
|
|
413
|
+
title: '🚨 MANDATORY CSS Module Import and Usage Pattern',
|
|
414
|
+
critical: 'This pattern is REQUIRED but differs based on context: developing INSIDE the design system vs USING the design system in another app.',
|
|
415
|
+
|
|
416
|
+
contextWarning: {
|
|
417
|
+
title: '⚠️ CRITICAL: Two Different Contexts',
|
|
418
|
+
description: 'The patterns differ significantly based on where you are developing',
|
|
419
|
+
contexts: {
|
|
420
|
+
insideDesignSystem: 'Building components IN the ui-design-system repository',
|
|
421
|
+
usingDesignSystem: 'Building features in an app that USES @spaced-out/ui-design-system',
|
|
422
|
+
},
|
|
423
|
+
howToKnow: 'Check package.json: If it has "name": "@spaced-out/ui-design-system", you are INSIDE. If it has "@spaced-out/ui-design-system" as a dependency, you are USING it.',
|
|
424
|
+
},
|
|
425
|
+
|
|
426
|
+
insideDesignSystem: {
|
|
427
|
+
title: '📦 Context: Developing INSIDE the Design System Repository',
|
|
428
|
+
fileNaming: {
|
|
429
|
+
tsx: 'ComponentName.tsx (PascalCase)',
|
|
430
|
+
css: 'ComponentName.module.css (PascalCase + .module.css)',
|
|
431
|
+
examples: ['DataTable.tsx + DataTable.module.css', 'UserProfile.tsx + UserProfile.module.css'],
|
|
432
|
+
},
|
|
433
|
+
cssImport: {
|
|
434
|
+
pattern: "import css from './ComponentName.module.css';",
|
|
435
|
+
examples: [
|
|
436
|
+
"import css from './DataTable.module.css';",
|
|
437
|
+
"import css from './UserProfile.module.css';",
|
|
438
|
+
],
|
|
439
|
+
},
|
|
440
|
+
tokenImports: {
|
|
441
|
+
pattern: "@value (tokenName) from '../../styles/variables/_category.css';",
|
|
442
|
+
explanation: 'Use RELATIVE paths to the styles directory',
|
|
443
|
+
examples: [
|
|
444
|
+
"@value (size480) from '../../styles/variables/_size.css';",
|
|
445
|
+
"@value (colorPrimary) from '../../styles/variables/_color.css';",
|
|
446
|
+
"@value (spaceMedium) from '../../styles/variables/_space.css';",
|
|
447
|
+
],
|
|
448
|
+
},
|
|
449
|
+
componentImports: {
|
|
450
|
+
pattern: "from 'src/components/ComponentName';",
|
|
451
|
+
examples: [
|
|
452
|
+
"import {Button} from 'src/components/Button';",
|
|
453
|
+
"import {Table} from 'src/components/Table';",
|
|
454
|
+
],
|
|
455
|
+
},
|
|
456
|
+
utilImports: {
|
|
457
|
+
pattern: "from 'src/utils/utilName';",
|
|
458
|
+
examples: [
|
|
459
|
+
"import classify from 'src/utils/classify';",
|
|
460
|
+
"import {generateTestId} from 'src/utils/qa';",
|
|
461
|
+
],
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
|
|
465
|
+
usingDesignSystem: {
|
|
466
|
+
title: '🏗️ Context: Using Design System in Another Application',
|
|
467
|
+
fileNaming: {
|
|
468
|
+
tsx: 'component-name.tsx (kebab-case)',
|
|
469
|
+
css: 'component-name.css (kebab-case, NO .module.css suffix)',
|
|
470
|
+
examples: ['data-table.tsx + data-table.css', 'user-profile.tsx + user-profile.css'],
|
|
471
|
+
critical: '🚨 File is .css NOT .module.css',
|
|
472
|
+
},
|
|
473
|
+
cssImport: {
|
|
474
|
+
pattern: "import css from './component-name.css';",
|
|
475
|
+
examples: [
|
|
476
|
+
"import css from './data-table.css';",
|
|
477
|
+
"import css from './user-profile.css';",
|
|
478
|
+
],
|
|
479
|
+
note: 'Notice: NO .module.css suffix in the filename',
|
|
480
|
+
},
|
|
481
|
+
tokenImports: {
|
|
482
|
+
pattern: "@value (tokenName) from '@spaced-out/ui-design-system/lib/styles/variables/_category.css';",
|
|
483
|
+
explanation: 'Use NPM PACKAGE path, not relative paths',
|
|
484
|
+
examples: [
|
|
485
|
+
"@value (size480) from '@spaced-out/ui-design-system/lib/styles/variables/_size.css';",
|
|
486
|
+
"@value (colorPrimary) from '@spaced-out/ui-design-system/lib/styles/variables/_color.css';",
|
|
487
|
+
"@value (spaceMedium) from '@spaced-out/ui-design-system/lib/styles/variables/_space.css';",
|
|
488
|
+
],
|
|
489
|
+
critical: '🚨 Must use @spaced-out/ui-design-system/lib/styles/... NOT relative paths',
|
|
490
|
+
},
|
|
491
|
+
componentImports: {
|
|
492
|
+
pattern: "from '@spaced-out/ui-design-system/lib/components/ComponentName';",
|
|
493
|
+
examples: [
|
|
494
|
+
"import {Button} from '@spaced-out/ui-design-system/lib/components/Button';",
|
|
495
|
+
"import {Table} from '@spaced-out/ui-design-system/lib/components/Table';",
|
|
496
|
+
],
|
|
497
|
+
},
|
|
498
|
+
utilImports: {
|
|
499
|
+
pattern: "from '@spaced-out/ui-design-system/lib/utils/utilName';",
|
|
500
|
+
examples: [
|
|
501
|
+
"import classify from '@spaced-out/ui-design-system/lib/utils/classify';",
|
|
502
|
+
"import {generateTestId} from '@spaced-out/ui-design-system/lib/utils/qa';",
|
|
503
|
+
],
|
|
504
|
+
},
|
|
505
|
+
},
|
|
506
|
+
|
|
507
|
+
comparisonTable: {
|
|
508
|
+
title: 'Side-by-Side Comparison',
|
|
509
|
+
aspect: {
|
|
510
|
+
tsxFileName: {
|
|
511
|
+
insideDS: 'ComponentName.tsx (PascalCase)',
|
|
512
|
+
usingDS: 'component-name.tsx (kebab-case)',
|
|
513
|
+
},
|
|
514
|
+
cssFileName: {
|
|
515
|
+
insideDS: 'ComponentName.module.css',
|
|
516
|
+
usingDS: 'component-name.css (NO .module)',
|
|
517
|
+
},
|
|
518
|
+
cssImport: {
|
|
519
|
+
insideDS: "import css from './ComponentName.module.css';",
|
|
520
|
+
usingDS: "import css from './component-name.css';",
|
|
521
|
+
},
|
|
522
|
+
tokenImport: {
|
|
523
|
+
insideDS: "@value (size480) from '../../styles/variables/_size.css';",
|
|
524
|
+
usingDS: "@value (size480) from '@spaced-out/ui-design-system/lib/styles/variables/_size.css';",
|
|
525
|
+
},
|
|
526
|
+
componentImport: {
|
|
527
|
+
insideDS: "import {Button} from 'src/components/Button';",
|
|
528
|
+
usingDS: "import {Button} from '@spaced-out/ui-design-system/lib/components/Button';",
|
|
529
|
+
},
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
correctImport: {
|
|
534
|
+
pattern: 'import css from \'./ComponentName.module.css\';',
|
|
535
|
+
explanation: 'CSS Modules MUST be imported as a default import with the variable name "css"',
|
|
536
|
+
examples: [
|
|
537
|
+
'import css from \'./DataTable.module.css\';',
|
|
538
|
+
'import css from \'./UserProfile.module.css\';',
|
|
539
|
+
'import css from \'./NavigationBar.module.css\';',
|
|
540
|
+
],
|
|
541
|
+
},
|
|
542
|
+
|
|
543
|
+
incorrectImports: {
|
|
544
|
+
sideEffect: {
|
|
545
|
+
code: 'import \'./ComponentName.module.css\';',
|
|
546
|
+
error: '❌ WRONG: Side-effect imports do not provide access to class names',
|
|
547
|
+
why: 'This imports the CSS but you cannot access the class names in your component',
|
|
548
|
+
},
|
|
549
|
+
namespace: {
|
|
550
|
+
code: 'import * as css from \'./ComponentName.module.css\';',
|
|
551
|
+
error: '❌ WRONG: Namespace imports are not supported for CSS Modules',
|
|
552
|
+
why: 'CSS Modules use default exports, not named exports',
|
|
553
|
+
},
|
|
554
|
+
wrongVariableName: {
|
|
555
|
+
code: 'import styles from \'./ComponentName.module.css\';',
|
|
556
|
+
error: '❌ WRONG: Variable name must be "css" not "styles" or any other name',
|
|
557
|
+
why: 'Consistency across the codebase requires using "css" as the variable name',
|
|
558
|
+
},
|
|
559
|
+
},
|
|
560
|
+
|
|
561
|
+
correctUsage: {
|
|
562
|
+
pattern: 'className={css.className}',
|
|
563
|
+
explanation: 'Class names are accessed as camelCase properties of the css object',
|
|
564
|
+
examples: [
|
|
565
|
+
'<div className={css.wrapper}>',
|
|
566
|
+
'<div className={css.tableHeader}>',
|
|
567
|
+
'<button className={css.submitButton}>',
|
|
568
|
+
'<span className={css.errorMessage}>',
|
|
569
|
+
],
|
|
570
|
+
withClassify: [
|
|
571
|
+
'className={classify(css.wrapper, css.active)}',
|
|
572
|
+
'className={classify(css.button, { [css.disabled]: isDisabled })}',
|
|
573
|
+
'className={classify(css.container, classNames?.wrapper)}',
|
|
574
|
+
],
|
|
575
|
+
},
|
|
576
|
+
|
|
577
|
+
incorrectUsage: {
|
|
578
|
+
stringLiteral: {
|
|
579
|
+
code: '<div className="wrapper">',
|
|
580
|
+
error: '❌ WRONG: Never use string literals for class names',
|
|
581
|
+
why: 'CSS Modules provide scoped class names that must be accessed via the css object',
|
|
582
|
+
},
|
|
583
|
+
stringInBraces: {
|
|
584
|
+
code: '<div className={\'wrapper\'}>',
|
|
585
|
+
error: '❌ WRONG: String literals in braces are still wrong',
|
|
586
|
+
why: 'You must use the css object property access: className={css.wrapper}',
|
|
587
|
+
},
|
|
588
|
+
kebabCase: {
|
|
589
|
+
code: '<div className={css[\'table-header\']}>',
|
|
590
|
+
error: '❌ WRONG: Use camelCase properties, not kebab-case strings',
|
|
591
|
+
why: 'CSS class names are automatically converted to camelCase properties',
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
|
|
595
|
+
cssFileNaming: {
|
|
596
|
+
inDesignSystem: {
|
|
597
|
+
pattern: 'ComponentName.module.css',
|
|
598
|
+
examples: [
|
|
599
|
+
'DataTable.module.css',
|
|
600
|
+
'UserProfile.module.css',
|
|
601
|
+
'NavigationBar.module.css',
|
|
602
|
+
],
|
|
603
|
+
},
|
|
604
|
+
inMainApp: {
|
|
605
|
+
pattern: 'component-name.module.css (kebab-case)',
|
|
606
|
+
examples: [
|
|
607
|
+
'data-table.module.css',
|
|
608
|
+
'user-profile.module.css',
|
|
609
|
+
'navigation-bar.module.css',
|
|
610
|
+
],
|
|
611
|
+
note: 'The main application uses kebab-case for file names',
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
|
|
615
|
+
cssSyntax: {
|
|
616
|
+
classDefinition: 'Use camelCase for class names in CSS files',
|
|
617
|
+
correct: [
|
|
618
|
+
'.wrapper { }',
|
|
619
|
+
'.tableHeader { }',
|
|
620
|
+
'.submitButton { }',
|
|
621
|
+
'.errorMessage { }',
|
|
622
|
+
],
|
|
623
|
+
incorrect: [
|
|
624
|
+
'.table-header { } // ❌ Use .tableHeader instead',
|
|
625
|
+
'.submit_button { } // ❌ Use .submitButton instead',
|
|
626
|
+
],
|
|
627
|
+
},
|
|
628
|
+
|
|
629
|
+
completeExamples: {
|
|
630
|
+
insideDesignSystem: {
|
|
631
|
+
title: 'Complete Example: Building INSIDE Design System',
|
|
632
|
+
tsx: `// DataTable.tsx (in ui-design-system repo)
|
|
633
|
+
import * as React from 'react';
|
|
634
|
+
import classify from 'src/utils/classify';
|
|
635
|
+
import {generateTestId} from 'src/utils/qa';
|
|
636
|
+
import {Button} from 'src/components/Button';
|
|
637
|
+
import {SearchInput} from 'src/components/SearchInput';
|
|
638
|
+
|
|
639
|
+
// 📦 INSIDE DESIGN SYSTEM: Import with .module.css and relative path
|
|
640
|
+
import css from './DataTable.module.css';
|
|
641
|
+
|
|
642
|
+
export const DataTable = () => (
|
|
643
|
+
<div className={css.wrapper}>
|
|
644
|
+
<div className={css.header}>
|
|
645
|
+
<SearchInput className={css.search} />
|
|
646
|
+
<Button>Filter</Button>
|
|
647
|
+
</div>
|
|
648
|
+
<table className={css.table}>
|
|
649
|
+
<thead className={css.thead}>
|
|
650
|
+
<tr>
|
|
651
|
+
<th className={css.th}>Name</th>
|
|
652
|
+
<th className={css.th}>Status</th>
|
|
653
|
+
</tr>
|
|
654
|
+
</thead>
|
|
655
|
+
</table>
|
|
656
|
+
</div>
|
|
657
|
+
);`,
|
|
658
|
+
css: `/* DataTable.module.css (in ui-design-system repo) */
|
|
659
|
+
/* 📦 INSIDE DESIGN SYSTEM: Import tokens with RELATIVE paths */
|
|
660
|
+
@value (
|
|
661
|
+
colorBorderPrimary,
|
|
662
|
+
colorBackgroundTertiary
|
|
663
|
+
) from '../../styles/variables/_color.css';
|
|
664
|
+
|
|
665
|
+
@value (
|
|
666
|
+
spaceSmall,
|
|
667
|
+
spaceMedium
|
|
668
|
+
) from '../../styles/variables/_space.css';
|
|
669
|
+
|
|
670
|
+
@value (size480) from '../../styles/variables/_size.css';
|
|
671
|
+
|
|
672
|
+
.wrapper {
|
|
673
|
+
display: flex;
|
|
674
|
+
flex-direction: column;
|
|
675
|
+
width: size480;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
.header {
|
|
679
|
+
padding: spaceMedium;
|
|
680
|
+
background: colorBackgroundTertiary;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
.table {
|
|
684
|
+
border: 1px solid colorBorderPrimary;
|
|
685
|
+
}`,
|
|
686
|
+
},
|
|
687
|
+
usingDesignSystem: {
|
|
688
|
+
title: 'Complete Example: USING Design System in Another App',
|
|
689
|
+
tsx: `// data-table.tsx (in your app repo, NOT in ui-design-system)
|
|
690
|
+
import * as React from 'react';
|
|
691
|
+
import classify from '@spaced-out/ui-design-system/lib/utils/classify';
|
|
692
|
+
import {generateTestId} from '@spaced-out/ui-design-system/lib/utils/qa';
|
|
693
|
+
import {Button} from '@spaced-out/ui-design-system/lib/components/Button';
|
|
694
|
+
import {SearchInput} from '@spaced-out/ui-design-system/lib/components/SearchInput';
|
|
695
|
+
|
|
696
|
+
// 🏗️ USING DESIGN SYSTEM: Import WITHOUT .module.css, kebab-case filename
|
|
697
|
+
import css from './data-table.css';
|
|
698
|
+
|
|
699
|
+
export const DataTable = () => (
|
|
700
|
+
<div className={css.wrapper}>
|
|
701
|
+
<div className={css.header}>
|
|
702
|
+
<SearchInput className={css.search} />
|
|
703
|
+
<Button>Filter</Button>
|
|
704
|
+
</div>
|
|
705
|
+
<table className={css.table}>
|
|
706
|
+
<thead className={css.thead}>
|
|
707
|
+
<tr>
|
|
708
|
+
<th className={css.th}>Name</th>
|
|
709
|
+
<th className={css.th}>Status</th>
|
|
710
|
+
</tr>
|
|
711
|
+
</thead>
|
|
712
|
+
</table>
|
|
713
|
+
</div>
|
|
714
|
+
);`,
|
|
715
|
+
css: `/* data-table.css (in your app repo, NOT in ui-design-system) */
|
|
716
|
+
/* 🏗️ USING DESIGN SYSTEM: Import tokens from NPM PACKAGE path */
|
|
717
|
+
@value (
|
|
718
|
+
colorBorderPrimary,
|
|
719
|
+
colorBackgroundTertiary
|
|
720
|
+
) from '@spaced-out/ui-design-system/lib/styles/variables/_color.css';
|
|
721
|
+
|
|
722
|
+
@value (
|
|
723
|
+
spaceSmall,
|
|
724
|
+
spaceMedium
|
|
725
|
+
) from '@spaced-out/ui-design-system/lib/styles/variables/_space.css';
|
|
726
|
+
|
|
727
|
+
@value (size480) from '@spaced-out/ui-design-system/lib/styles/variables/_size.css';
|
|
728
|
+
|
|
729
|
+
.wrapper {
|
|
730
|
+
display: flex;
|
|
731
|
+
flex-direction: column;
|
|
732
|
+
width: size480;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
.header {
|
|
736
|
+
padding: spaceMedium;
|
|
737
|
+
background: colorBackgroundTertiary;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
.table {
|
|
741
|
+
border: 1px solid colorBorderPrimary;
|
|
742
|
+
}`,
|
|
743
|
+
},
|
|
744
|
+
},
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
|
|
327
748
|
/**
|
|
328
749
|
* Get design token import guidelines
|
|
329
750
|
*/
|
|
@@ -483,12 +904,22 @@ function getComponentTemplate() {
|
|
|
483
904
|
import classify from 'src/utils/classify';
|
|
484
905
|
import {generateTestId} from 'src/utils/qa';
|
|
485
906
|
|
|
907
|
+
// 🚨 CRITICAL: CSS Modules MUST be imported as default import with variable name "css"
|
|
908
|
+
// ✅ Correct: import css from './ComponentName.module.css';
|
|
909
|
+
// ❌ WRONG: import './ComponentName.module.css';
|
|
910
|
+
// ❌ WRONG: import * as css from './ComponentName.module.css';
|
|
911
|
+
// ❌ WRONG: import styles from './ComponentName.module.css';
|
|
486
912
|
import css from 'src/components/ComponentName/ComponentName.module.css';
|
|
487
913
|
|
|
488
914
|
// IMPORTANT: Use pure TypeScript - NO Flow types
|
|
489
915
|
// ✅ Correct: React.forwardRef<HTMLDivElement, Props>
|
|
490
916
|
// ❌ Wrong: Flow.AbstractComponent<Props, HTMLDivElement>
|
|
491
917
|
|
|
918
|
+
// IMPORTANT: Use className with CSS Module property access
|
|
919
|
+
// ✅ Correct: className={css.wrapper}
|
|
920
|
+
// ❌ WRONG: className="wrapper"
|
|
921
|
+
// ❌ WRONG: className={'wrapper'}
|
|
922
|
+
|
|
492
923
|
type ClassNames = Readonly<{
|
|
493
924
|
wrapper?: string;
|
|
494
925
|
}>;
|
|
@@ -669,6 +1100,8 @@ const server = new Server(
|
|
|
669
1100
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
670
1101
|
const components = getAllComponents();
|
|
671
1102
|
const hooks = getAllHooks();
|
|
1103
|
+
const utils = getAllUtils();
|
|
1104
|
+
const types = getAllTypes();
|
|
672
1105
|
|
|
673
1106
|
const resources = [
|
|
674
1107
|
{
|
|
@@ -689,6 +1122,18 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
|
689
1122
|
mimeType: 'application/json',
|
|
690
1123
|
description: `List of all ${hooks.length} available hooks`,
|
|
691
1124
|
},
|
|
1125
|
+
{
|
|
1126
|
+
uri: 'genesis://utils',
|
|
1127
|
+
name: 'All Utils',
|
|
1128
|
+
mimeType: 'application/json',
|
|
1129
|
+
description: `List of all ${utils.length} available utility modules`,
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
uri: 'genesis://types',
|
|
1133
|
+
name: 'All Types',
|
|
1134
|
+
mimeType: 'application/json',
|
|
1135
|
+
description: `List of all ${types.length} available type definitions`,
|
|
1136
|
+
},
|
|
692
1137
|
{
|
|
693
1138
|
uri: 'genesis://tokens',
|
|
694
1139
|
name: 'Design Tokens',
|
|
@@ -717,6 +1162,26 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
|
717
1162
|
});
|
|
718
1163
|
});
|
|
719
1164
|
|
|
1165
|
+
// Add individual util resources
|
|
1166
|
+
utils.forEach(util => {
|
|
1167
|
+
resources.push({
|
|
1168
|
+
uri: `genesis://util/${util}`,
|
|
1169
|
+
name: `Util: ${util}`,
|
|
1170
|
+
mimeType: 'text/markdown',
|
|
1171
|
+
description: `Utility functions for ${util}`,
|
|
1172
|
+
});
|
|
1173
|
+
});
|
|
1174
|
+
|
|
1175
|
+
// Add individual type resources
|
|
1176
|
+
types.forEach(type => {
|
|
1177
|
+
resources.push({
|
|
1178
|
+
uri: `genesis://type/${type}`,
|
|
1179
|
+
name: `Type: ${type}`,
|
|
1180
|
+
mimeType: 'text/markdown',
|
|
1181
|
+
description: `Type definitions for ${type}`,
|
|
1182
|
+
});
|
|
1183
|
+
});
|
|
1184
|
+
|
|
720
1185
|
return { resources };
|
|
721
1186
|
});
|
|
722
1187
|
|
|
@@ -736,6 +1201,8 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
|
736
1201
|
|
|
737
1202
|
- **Components:** ${Object.keys(designSystemData.components).length}
|
|
738
1203
|
- **Hooks:** ${Object.keys(designSystemData.hooks).length}
|
|
1204
|
+
- **Utils:** ${Object.keys(designSystemData.utils || {}).length}
|
|
1205
|
+
- **Types:** ${Object.keys(designSystemData.types || {}).length}
|
|
739
1206
|
- **Design Token Categories:** ${Object.keys(designSystemData.tokens).length}
|
|
740
1207
|
|
|
741
1208
|
## Available Components
|
|
@@ -746,6 +1213,14 @@ ${getAllComponents().map(c => `- ${c}`).join('\n')}
|
|
|
746
1213
|
|
|
747
1214
|
${getAllHooks().map(h => `- ${h}`).join('\n')}
|
|
748
1215
|
|
|
1216
|
+
## Available Utils
|
|
1217
|
+
|
|
1218
|
+
${getAllUtils().map(u => `- ${u}`).join('\n')}
|
|
1219
|
+
|
|
1220
|
+
## Available Types
|
|
1221
|
+
|
|
1222
|
+
${getAllTypes().map(t => `- ${t}`).join('\n')}
|
|
1223
|
+
|
|
749
1224
|
## Design Token Categories
|
|
750
1225
|
|
|
751
1226
|
${Object.keys(designSystemData.tokens).map(cat => `- **${cat}**: ${Object.keys(designSystemData.tokens[cat]).length} file(s)`).join('\n')}
|
|
@@ -788,6 +1263,32 @@ ${Object.keys(designSystemData.tokens).map(cat => `- **${cat}**: ${Object.keys(d
|
|
|
788
1263
|
};
|
|
789
1264
|
}
|
|
790
1265
|
|
|
1266
|
+
if (uri === 'genesis://utils') {
|
|
1267
|
+
const utils = getAllUtils();
|
|
1268
|
+
return {
|
|
1269
|
+
contents: [
|
|
1270
|
+
{
|
|
1271
|
+
uri,
|
|
1272
|
+
mimeType: 'application/json',
|
|
1273
|
+
text: JSON.stringify(utils, null, 2),
|
|
1274
|
+
},
|
|
1275
|
+
],
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
if (uri === 'genesis://types') {
|
|
1280
|
+
const types = getAllTypes();
|
|
1281
|
+
return {
|
|
1282
|
+
contents: [
|
|
1283
|
+
{
|
|
1284
|
+
uri,
|
|
1285
|
+
mimeType: 'application/json',
|
|
1286
|
+
text: JSON.stringify(types, null, 2),
|
|
1287
|
+
},
|
|
1288
|
+
],
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
|
|
791
1292
|
if (uri === 'genesis://tokens') {
|
|
792
1293
|
const tokens = getAllDesignTokens();
|
|
793
1294
|
return {
|
|
@@ -850,6 +1351,18 @@ ${Object.keys(designSystemData.tokens).map(cat => `- **${cat}**: ${Object.keys(d
|
|
|
850
1351
|
markdown += '\n```\n\n';
|
|
851
1352
|
}
|
|
852
1353
|
|
|
1354
|
+
// Display additional files (sub-components)
|
|
1355
|
+
if (details.files.additional && Object.keys(details.files.additional).length > 0) {
|
|
1356
|
+
markdown += `## Additional Files (Sub-components)\n\n`;
|
|
1357
|
+
|
|
1358
|
+
for (const [fileName, fileData] of Object.entries(details.files.additional)) {
|
|
1359
|
+
markdown += `### ${fileName}\n\n`;
|
|
1360
|
+
markdown += '```typescript\n';
|
|
1361
|
+
markdown += fileData.content;
|
|
1362
|
+
markdown += '\n```\n\n';
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
|
|
853
1366
|
return {
|
|
854
1367
|
contents: [
|
|
855
1368
|
{
|
|
@@ -898,6 +1411,67 @@ ${Object.keys(designSystemData.tokens).map(cat => `- **${cat}**: ${Object.keys(d
|
|
|
898
1411
|
};
|
|
899
1412
|
}
|
|
900
1413
|
|
|
1414
|
+
if (uri.startsWith('genesis://util/')) {
|
|
1415
|
+
const utilName = uri.replace('genesis://util/', '');
|
|
1416
|
+
const details = getUtilDetails(utilName);
|
|
1417
|
+
|
|
1418
|
+
if (!details) {
|
|
1419
|
+
throw new Error(`Util ${utilName} not found`);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
let markdown = `# ${utilName}\n\n`;
|
|
1423
|
+
markdown += `**Path:** \`${details.path}\`\n\n`;
|
|
1424
|
+
markdown += `**Files:** ${details.allFiles.join(', ')}\n\n`;
|
|
1425
|
+
|
|
1426
|
+
// Display all files in the util module
|
|
1427
|
+
if (details.files && Object.keys(details.files).length > 0) {
|
|
1428
|
+
markdown += `## Utility Files\n\n`;
|
|
1429
|
+
|
|
1430
|
+
for (const [fileName, fileData] of Object.entries(details.files)) {
|
|
1431
|
+
markdown += `### ${fileName}\n\n`;
|
|
1432
|
+
markdown += '```typescript\n';
|
|
1433
|
+
markdown += fileData.content;
|
|
1434
|
+
markdown += '\n```\n\n';
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
return {
|
|
1439
|
+
contents: [
|
|
1440
|
+
{
|
|
1441
|
+
uri,
|
|
1442
|
+
mimeType: 'text/markdown',
|
|
1443
|
+
text: markdown,
|
|
1444
|
+
},
|
|
1445
|
+
],
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
if (uri.startsWith('genesis://type/')) {
|
|
1450
|
+
const typeName = uri.replace('genesis://type/', '');
|
|
1451
|
+
const details = getTypeDetails(typeName);
|
|
1452
|
+
|
|
1453
|
+
if (!details) {
|
|
1454
|
+
throw new Error(`Type ${typeName} not found`);
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
let markdown = `# ${typeName}\n\n`;
|
|
1458
|
+
markdown += `**Path:** \`${details.path}\`\n\n`;
|
|
1459
|
+
markdown += `## Type Definitions\n\n`;
|
|
1460
|
+
markdown += '```typescript\n';
|
|
1461
|
+
markdown += details.content;
|
|
1462
|
+
markdown += '\n```\n\n';
|
|
1463
|
+
|
|
1464
|
+
return {
|
|
1465
|
+
contents: [
|
|
1466
|
+
{
|
|
1467
|
+
uri,
|
|
1468
|
+
mimeType: 'text/markdown',
|
|
1469
|
+
text: markdown,
|
|
1470
|
+
},
|
|
1471
|
+
],
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
|
|
901
1475
|
throw new Error(`Unknown resource: ${uri}`);
|
|
902
1476
|
});
|
|
903
1477
|
|
|
@@ -965,6 +1539,50 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
965
1539
|
required: ['name'],
|
|
966
1540
|
},
|
|
967
1541
|
},
|
|
1542
|
+
{
|
|
1543
|
+
name: 'list_utils',
|
|
1544
|
+
description: 'List all available utility modules in the design system',
|
|
1545
|
+
inputSchema: {
|
|
1546
|
+
type: 'object',
|
|
1547
|
+
properties: {},
|
|
1548
|
+
},
|
|
1549
|
+
},
|
|
1550
|
+
{
|
|
1551
|
+
name: 'get_util',
|
|
1552
|
+
description: 'Get detailed information about a specific utility module including all its functions',
|
|
1553
|
+
inputSchema: {
|
|
1554
|
+
type: 'object',
|
|
1555
|
+
properties: {
|
|
1556
|
+
name: {
|
|
1557
|
+
type: 'string',
|
|
1558
|
+
description: 'Name of the utility module (e.g., "classify", "qa", "dom")',
|
|
1559
|
+
},
|
|
1560
|
+
},
|
|
1561
|
+
required: ['name'],
|
|
1562
|
+
},
|
|
1563
|
+
},
|
|
1564
|
+
{
|
|
1565
|
+
name: 'list_types',
|
|
1566
|
+
description: 'List all available type definitions in the design system',
|
|
1567
|
+
inputSchema: {
|
|
1568
|
+
type: 'object',
|
|
1569
|
+
properties: {},
|
|
1570
|
+
},
|
|
1571
|
+
},
|
|
1572
|
+
{
|
|
1573
|
+
name: 'get_type',
|
|
1574
|
+
description: 'Get detailed information about a specific type definition file',
|
|
1575
|
+
inputSchema: {
|
|
1576
|
+
type: 'object',
|
|
1577
|
+
properties: {
|
|
1578
|
+
name: {
|
|
1579
|
+
type: 'string',
|
|
1580
|
+
description: 'Name of the type file (e.g., "common", "typography", "charts")',
|
|
1581
|
+
},
|
|
1582
|
+
},
|
|
1583
|
+
required: ['name'],
|
|
1584
|
+
},
|
|
1585
|
+
},
|
|
968
1586
|
{
|
|
969
1587
|
name: 'get_design_tokens',
|
|
970
1588
|
description: 'Get all design tokens including colors, spacing, typography, shadows, etc.',
|
|
@@ -986,6 +1604,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
986
1604
|
properties: {},
|
|
987
1605
|
},
|
|
988
1606
|
},
|
|
1607
|
+
{
|
|
1608
|
+
name: 'get_css_module_import_patterns',
|
|
1609
|
+
description: '🚨 MANDATORY: Get the required CSS Module import and usage pattern based on context. This tool shows TWO different patterns: (1) Building INSIDE ui-design-system repo: .module.css files, PascalCase, relative imports. (2) USING design system in another app: .css files, kebab-case, @spaced-out/ui-design-system imports. MUST be called FIRST before generating any component to understand context and use correct patterns. Failure to follow context-specific patterns will cause import errors.',
|
|
1610
|
+
inputSchema: {
|
|
1611
|
+
type: 'object',
|
|
1612
|
+
properties: {},
|
|
1613
|
+
},
|
|
1614
|
+
},
|
|
989
1615
|
{
|
|
990
1616
|
name: 'get_design_token_import_guidelines',
|
|
991
1617
|
description: 'Get guidelines and best practices for importing design tokens in CSS Module files. This includes the correct import paths, available token files, and examples of correct vs incorrect imports. ALWAYS call this function before creating CSS Module files to ensure correct token imports.',
|
|
@@ -996,7 +1622,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
996
1622
|
},
|
|
997
1623
|
{
|
|
998
1624
|
name: 'get_css_module_guidelines',
|
|
999
|
-
description: 'Get comprehensive CSS Module styling guidelines including class naming conventions, token usage, icon color patterns, and common mistakes to avoid. CRITICAL: Call this
|
|
1625
|
+
description: 'Get comprehensive CSS Module styling guidelines including MANDATORY import pattern (import css from "./file.module.css"), class naming conventions, token usage, icon color patterns, and common mistakes to avoid. 🚨 CRITICAL: Call this BEFORE creating or modifying any component files to ensure correct CSS Module usage and design system patterns. This includes the mandatory pattern: import css from "./Component.module.css" and className={css.className}.',
|
|
1000
1626
|
inputSchema: {
|
|
1001
1627
|
type: 'object',
|
|
1002
1628
|
properties: {},
|
|
@@ -1126,6 +1752,76 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1126
1752
|
};
|
|
1127
1753
|
}
|
|
1128
1754
|
|
|
1755
|
+
case 'list_utils': {
|
|
1756
|
+
const utils = getAllUtils();
|
|
1757
|
+
return {
|
|
1758
|
+
content: [
|
|
1759
|
+
{
|
|
1760
|
+
type: 'text',
|
|
1761
|
+
text: JSON.stringify(utils, null, 2),
|
|
1762
|
+
},
|
|
1763
|
+
],
|
|
1764
|
+
};
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
case 'get_util': {
|
|
1768
|
+
const details = getUtilDetails(args.name);
|
|
1769
|
+
if (!details) {
|
|
1770
|
+
return {
|
|
1771
|
+
content: [
|
|
1772
|
+
{
|
|
1773
|
+
type: 'text',
|
|
1774
|
+
text: `Util "${args.name}" not found`,
|
|
1775
|
+
},
|
|
1776
|
+
],
|
|
1777
|
+
isError: true,
|
|
1778
|
+
};
|
|
1779
|
+
}
|
|
1780
|
+
return {
|
|
1781
|
+
content: [
|
|
1782
|
+
{
|
|
1783
|
+
type: 'text',
|
|
1784
|
+
text: JSON.stringify(details, null, 2),
|
|
1785
|
+
},
|
|
1786
|
+
],
|
|
1787
|
+
};
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
case 'list_types': {
|
|
1791
|
+
const types = getAllTypes();
|
|
1792
|
+
return {
|
|
1793
|
+
content: [
|
|
1794
|
+
{
|
|
1795
|
+
type: 'text',
|
|
1796
|
+
text: JSON.stringify(types, null, 2),
|
|
1797
|
+
},
|
|
1798
|
+
],
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
case 'get_type': {
|
|
1803
|
+
const details = getTypeDetails(args.name);
|
|
1804
|
+
if (!details) {
|
|
1805
|
+
return {
|
|
1806
|
+
content: [
|
|
1807
|
+
{
|
|
1808
|
+
type: 'text',
|
|
1809
|
+
text: `Type "${args.name}" not found`,
|
|
1810
|
+
},
|
|
1811
|
+
],
|
|
1812
|
+
isError: true,
|
|
1813
|
+
};
|
|
1814
|
+
}
|
|
1815
|
+
return {
|
|
1816
|
+
content: [
|
|
1817
|
+
{
|
|
1818
|
+
type: 'text',
|
|
1819
|
+
text: JSON.stringify(details, null, 2),
|
|
1820
|
+
},
|
|
1821
|
+
],
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1129
1825
|
case 'get_design_tokens': {
|
|
1130
1826
|
const allTokens = getAllDesignTokens();
|
|
1131
1827
|
const tokens = args.category ? { [args.category]: allTokens[args.category] } : allTokens;
|
|
@@ -1151,6 +1847,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1151
1847
|
};
|
|
1152
1848
|
}
|
|
1153
1849
|
|
|
1850
|
+
case 'get_css_module_import_patterns': {
|
|
1851
|
+
const patterns = getCSSModuleImportPatterns();
|
|
1852
|
+
return {
|
|
1853
|
+
content: [
|
|
1854
|
+
{
|
|
1855
|
+
type: 'text',
|
|
1856
|
+
text: JSON.stringify(patterns, null, 2),
|
|
1857
|
+
},
|
|
1858
|
+
],
|
|
1859
|
+
};
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1154
1862
|
case 'get_design_token_import_guidelines': {
|
|
1155
1863
|
const guidelines = getDesignTokenImportGuidelines();
|
|
1156
1864
|
return {
|