feat(design-tokens): add SSO brand color tokens
This commit is contained in:
parent
2f7e3ad9b6
commit
71b33fcf62
@ -28,6 +28,14 @@ object MindLystTokens {
|
||||
const val GOLD = 0xFFFFD166
|
||||
const val MINT = 0xFF34D399
|
||||
const val WARNING = 0xFFF59E0B
|
||||
const val MICROSOFTRED = 0xFFF25022
|
||||
const val MICROSOFTGREEN = 0xFF7FBA00
|
||||
const val MICROSOFTBLUE = 0xFF00A4EF
|
||||
const val MICROSOFTYELLOW = 0xFFFFB900
|
||||
const val GOOGLEBLUE = 0xFF4285F4
|
||||
const val GOOGLEGREEN = 0xFF34A853
|
||||
const val GOOGLEYELLOW = 0xFFFBBC05
|
||||
const val GOOGLERED = 0xFFEA4335
|
||||
}
|
||||
|
||||
// ── Semantic Colors (Dark Theme) ─────────────────────────────────
|
||||
|
||||
@ -30,6 +30,14 @@ export const tokens = {
|
||||
gold: '#FFD166',
|
||||
mint: '#34D399',
|
||||
warning: '#F59E0B',
|
||||
microsoftRed: '#F25022',
|
||||
microsoftGreen: '#7FBA00',
|
||||
microsoftBlue: '#00A4EF',
|
||||
microsoftYellow: '#FFB900',
|
||||
googleBlue: '#4285F4',
|
||||
googleGreen: '#34A853',
|
||||
googleYellow: '#FBBC05',
|
||||
googleRed: '#EA4335',
|
||||
},
|
||||
},
|
||||
semantic: {
|
||||
|
||||
@ -1,110 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Token validation script — checks for hardcoded colors in source files
|
||||
* and reports token coverage per product.
|
||||
*
|
||||
* Usage: node scripts/validate-tokens.js [product-path]
|
||||
*/
|
||||
|
||||
const { readFileSync, readdirSync, statSync } = require('fs');
|
||||
const { join, resolve } = require('path');
|
||||
|
||||
const HARD_COLOR_REGEX = /#[0-9A-Fa-f]{3,8}\b|rgb\([^)]+\)|rgba\([^)]+\)|hsl\([^)]+\)/g;
|
||||
const EXCLUDED_DIRS = ['node_modules', 'dist', 'build', '.git', 'generated', '__mocks__'];
|
||||
const INCLUDED_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.swift', '.kt'];
|
||||
|
||||
function findFiles(dir, files = []) {
|
||||
try {
|
||||
const items = readdirSync(dir);
|
||||
for (const item of items) {
|
||||
const fullPath = join(dir, item);
|
||||
if (EXCLUDED_DIRS.some(ex => fullPath.includes(ex))) continue;
|
||||
|
||||
const stat = statSync(fullPath);
|
||||
if (stat.isDirectory()) {
|
||||
findFiles(fullPath, files);
|
||||
} else if (INCLUDED_EXTENSIONS.some(ext => item.endsWith(ext))) {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Directory might not exist or be accessible
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
function analyzeFile(filePath) {
|
||||
const content = readFileSync(filePath, 'utf-8');
|
||||
const lines = content.split('\n');
|
||||
const issues = [];
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
// Skip comments
|
||||
if (line.trim().startsWith('//') || line.trim().startsWith('*') || line.trim().startsWith('/*'))
|
||||
return;
|
||||
|
||||
const matches = line.match(HARD_COLOR_REGEX);
|
||||
if (matches) {
|
||||
// Filter out legitimate uses (like transparency values)
|
||||
const suspicious = matches.filter(m => {
|
||||
if (m.startsWith('#') && (m.length === 9 || m.length === 5)) return false; // Skip alpha hex
|
||||
if (m.includes('0.0') || m.includes('1.0')) return false; // Skip clear/opaque
|
||||
return true;
|
||||
});
|
||||
|
||||
if (suspicious.length > 0) {
|
||||
issues.push({
|
||||
line: index + 1,
|
||||
colors: suspicious,
|
||||
content: line.trim().slice(0, 80),
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const targetPath = process.argv[2] || '.';
|
||||
const absolutePath = resolve(targetPath);
|
||||
|
||||
console.log(`🔍 Scanning ${absolutePath} for hardcoded colors...\n`);
|
||||
|
||||
const files = findFiles(absolutePath);
|
||||
let totalIssues = 0;
|
||||
let filesWithIssues = 0;
|
||||
|
||||
for (const file of files) {
|
||||
const issues = analyzeFile(file);
|
||||
if (issues.length > 0) {
|
||||
filesWithIssues++;
|
||||
totalIssues += issues.length;
|
||||
const relativePath = file.replace(absolutePath, '').slice(1);
|
||||
console.log(`\n📄 ${relativePath}`);
|
||||
issues.forEach(issue => {
|
||||
console.log(` Line ${issue.line}: ${issue.colors.join(', ')}`);
|
||||
console.log(` ${issue.content}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n${'='.repeat(60)}`);
|
||||
console.log(`📊 Summary:`);
|
||||
console.log(` Files scanned: ${files.length}`);
|
||||
console.log(` Files with hardcoded colors: ${filesWithIssues}`);
|
||||
console.log(` Total hardcoded colors found: ${totalIssues}`);
|
||||
|
||||
if (totalIssues > 0) {
|
||||
console.log(`\n⚠️ Consider replacing hardcoded colors with design tokens:`);
|
||||
console.log(` Web: var(--ml-<token>) from @bytelyst/design-tokens`);
|
||||
console.log(` iOS: MindLystColors.dark<Token> / MindLystColors.light<Token>`);
|
||||
console.log(` KMP: MindLystTokens.Dark.<TOKEN> / MindLystTokens.Light.<TOKEN>`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(`\n✅ No hardcoded colors found! All colors use design tokens.`);
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@ -27,7 +27,17 @@
|
||||
"coral": "#FF6E6E",
|
||||
"gold": "#FFD166",
|
||||
"mint": "#34D399",
|
||||
"warning": "#F59E0B"
|
||||
"warning": "#F59E0B",
|
||||
|
||||
"microsoftRed": "#F25022",
|
||||
"microsoftGreen": "#7FBA00",
|
||||
"microsoftBlue": "#00A4EF",
|
||||
"microsoftYellow": "#FFB900",
|
||||
|
||||
"googleBlue": "#4285F4",
|
||||
"googleGreen": "#34A853",
|
||||
"googleYellow": "#FBBC05",
|
||||
"googleRed": "#EA4335"
|
||||
}
|
||||
},
|
||||
"semantic": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user