Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
This commit is contained in:
278
admin-ui/js/components/tools/ds-quick-wins-script.js
Normal file
278
admin-ui/js/components/tools/ds-quick-wins-script.js
Normal file
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* ds-quick-wins-script.js
|
||||
* Quick Wins analyzer - finds low-effort, high-impact design system improvements
|
||||
* MVP2: Identifies inconsistencies and suggests standardization opportunities
|
||||
*/
|
||||
|
||||
export default class QuickWinsScript extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.analysisResults = null;
|
||||
this.isAnalyzing = false;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
render() {
|
||||
this.innerHTML = `
|
||||
<div style="padding: 24px; height: 100%; overflow-y: auto;">
|
||||
<div style="margin-bottom: 24px;">
|
||||
<h1 style="margin: 0 0 8px 0; font-size: 24px;">Design System Quick Wins</h1>
|
||||
<p style="margin: 0; color: var(--vscode-text-dim);">
|
||||
Identify low-effort, high-impact improvements to your design system
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Analysis Controls -->
|
||||
<div style="background: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; padding: 16px; margin-bottom: 24px;">
|
||||
<div style="margin-bottom: 12px;">
|
||||
<label style="display: block; font-size: 12px; font-weight: 500; margin-bottom: 8px;">
|
||||
What to analyze
|
||||
</label>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px;">
|
||||
<label style="display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: 12px;">
|
||||
<input type="checkbox" id="check-tokens" checked />
|
||||
Design Tokens
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: 12px;">
|
||||
<input type="checkbox" id="check-colors" checked />
|
||||
Color Usage
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: 12px;">
|
||||
<input type="checkbox" id="check-spacing" checked />
|
||||
Spacing Values
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: 12px;">
|
||||
<input type="checkbox" id="check-typography" checked />
|
||||
Typography
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="analyze-btn" aria-label="Analyze design system for improvement opportunities" style="
|
||||
width: 100%;
|
||||
padding: 8px 16px;
|
||||
background: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
">Analyze Design System</button>
|
||||
</div>
|
||||
|
||||
<!-- Loading State -->
|
||||
<div id="loading-container" style="display: none; text-align: center; padding: 48px; background: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px;">
|
||||
<div style="font-size: 24px; margin-bottom: 12px;">⏳</div>
|
||||
<div style="font-size: 12px; color: var(--vscode-text-dim);">
|
||||
Analyzing design system...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Results Container -->
|
||||
<div id="results-container" style="display: none;">
|
||||
<!-- Results will be inserted here -->
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
const analyzeBtn = this.querySelector('#analyze-btn');
|
||||
if (analyzeBtn) {
|
||||
analyzeBtn.addEventListener('click', () => this.analyzeDesignSystem());
|
||||
}
|
||||
}
|
||||
|
||||
async analyzeDesignSystem() {
|
||||
this.isAnalyzing = true;
|
||||
const loadingContainer = this.querySelector('#loading-container');
|
||||
const resultsContainer = this.querySelector('#results-container');
|
||||
|
||||
loadingContainer.style.display = 'block';
|
||||
resultsContainer.style.display = 'none';
|
||||
|
||||
// Simulate analysis
|
||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
||||
|
||||
this.analysisResults = this.generateAnalysisResults();
|
||||
this.renderResults();
|
||||
|
||||
loadingContainer.style.display = 'none';
|
||||
resultsContainer.style.display = 'block';
|
||||
this.isAnalyzing = false;
|
||||
}
|
||||
|
||||
generateAnalysisResults() {
|
||||
return [
|
||||
{
|
||||
title: 'Consolidate Color Palette',
|
||||
impact: 'high',
|
||||
effort: 'low',
|
||||
description: 'Found 23 unique colors in codebase, but only 8 are documented tokens. Consolidate to reduce cognitive load.',
|
||||
recommendation: 'Extract 15 undocumented colors and add to token library',
|
||||
estimate: '2 hours',
|
||||
files_affected: 34
|
||||
},
|
||||
{
|
||||
title: 'Standardize Spacing Scale',
|
||||
impact: 'high',
|
||||
effort: 'low',
|
||||
description: 'Spacing values are inconsistent (4px, 6px, 8px, 12px, 16px, 20px, 24px, 32px). Reduce to 6-8 standard values.',
|
||||
recommendation: 'Use 4px, 8px, 12px, 16px, 24px, 32px as standard spacing scale',
|
||||
estimate: '3 hours',
|
||||
files_affected: 67
|
||||
},
|
||||
{
|
||||
title: 'Create Typography System',
|
||||
impact: 'high',
|
||||
effort: 'medium',
|
||||
description: 'Typography scales vary across components. Establish consistent type hierarchy.',
|
||||
recommendation: 'Define 5 font sizes (12px, 14px, 16px, 18px, 24px) with line-height ratios',
|
||||
estimate: '4 hours',
|
||||
files_affected: 45
|
||||
},
|
||||
{
|
||||
title: 'Document Component Variants',
|
||||
impact: 'medium',
|
||||
effort: 'low',
|
||||
description: 'Button component has 7 undocumented variants in use. Update documentation.',
|
||||
recommendation: 'Add variant definitions and usage guidelines to Storybook',
|
||||
estimate: '1 hour',
|
||||
files_affected: 12
|
||||
},
|
||||
{
|
||||
title: 'Establish Naming Convention',
|
||||
impact: 'medium',
|
||||
effort: 'low',
|
||||
description: 'Token names are inconsistent (color-primary vs primaryColor vs primary-color).',
|
||||
recommendation: 'Adopt kebab-case convention: color-primary, spacing-sm, font-body',
|
||||
estimate: '2 hours',
|
||||
files_affected: 89
|
||||
},
|
||||
{
|
||||
title: 'Create Shadow System',
|
||||
impact: 'medium',
|
||||
effort: 'medium',
|
||||
description: 'Shadow values are hardcoded throughout. Create reusable shadow tokens.',
|
||||
recommendation: 'Define 3-4 elevation levels: shadow-sm, shadow-md, shadow-lg, shadow-xl',
|
||||
estimate: '2 hours',
|
||||
files_affected: 23
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
renderResults() {
|
||||
const container = this.querySelector('#results-container');
|
||||
|
||||
const results = this.analysisResults;
|
||||
const highImpact = results.filter(r => r.impact === 'high');
|
||||
const mediumImpact = results.filter(r => r.impact === 'medium');
|
||||
const totalFiles = results.reduce((sum, r) => sum + r.files_affected, 0);
|
||||
|
||||
// Build stats efficiently
|
||||
const statsHtml = this.buildStatsCards(results.length, highImpact.length, totalFiles);
|
||||
|
||||
// Build cards with memoization
|
||||
const highImpactHtml = highImpact.map(win => this.renderWinCard(win)).join('');
|
||||
const mediumImpactHtml = mediumImpact.map(win => this.renderWinCard(win)).join('');
|
||||
|
||||
let html = `
|
||||
<div style="margin-bottom: 24px;">
|
||||
${statsHtml}
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 24px;">
|
||||
<h2 style="margin: 0 0 12px 0; font-size: 14px; color: #FF9800;">High Impact Opportunities</h2>
|
||||
${highImpactHtml}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 style="margin: 0 0 12px 0; font-size: 14px; color: #0066CC;">Medium Impact Opportunities</h2>
|
||||
${mediumImpactHtml}
|
||||
</div>
|
||||
`;
|
||||
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
buildStatsCards(total, highCount, fileCount) {
|
||||
return `
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 24px;">
|
||||
<div style="background: var(--vscode-sidebar); padding: 12px; border-radius: 4px; text-align: center;">
|
||||
<div style="font-size: 24px; font-weight: 600; color: #4CAF50;">${total}</div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim);">Total Opportunities</div>
|
||||
</div>
|
||||
<div style="background: var(--vscode-sidebar); padding: 12px; border-radius: 4px; text-align: center;">
|
||||
<div style="font-size: 24px; font-weight: 600; color: #FF9800;">${highCount}</div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim);">High Impact</div>
|
||||
</div>
|
||||
<div style="background: var(--vscode-sidebar); padding: 12px; border-radius: 4px; text-align: center;">
|
||||
<div style="font-size: 24px; font-weight: 600; color: #0066CC;">${fileCount}</div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim);">Files Affected</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
renderWinCard(win) {
|
||||
const impactColor = win.impact === 'high' ? '#FF9800' : '#0066CC';
|
||||
const effortColor = win.effort === 'low' ? '#4CAF50' : win.effort === 'medium' ? '#FF9800' : '#F44336';
|
||||
|
||||
return `
|
||||
<div style="
|
||||
background: var(--vscode-sidebar);
|
||||
border: 1px solid var(--vscode-border);
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
margin-bottom: 12px;
|
||||
">
|
||||
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 8px;">
|
||||
<div style="font-weight: 500; font-size: 13px;">${win.title}</div>
|
||||
<div style="display: flex; gap: 6px;">
|
||||
<span style="
|
||||
padding: 2px 8px;
|
||||
border-radius: 2px;
|
||||
font-size: 10px;
|
||||
background: ${impactColor};
|
||||
color: white;
|
||||
">${win.impact} impact</span>
|
||||
<span style="
|
||||
padding: 2px 8px;
|
||||
border-radius: 2px;
|
||||
font-size: 10px;
|
||||
background: ${effortColor};
|
||||
color: white;
|
||||
">${win.effort} effort</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p style="margin: 0 0 8px 0; font-size: 12px; color: var(--vscode-text-dim);">
|
||||
${win.description}
|
||||
</p>
|
||||
|
||||
<div style="
|
||||
background: var(--vscode-bg);
|
||||
padding: 8px;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 11px;
|
||||
color: #CE9178;
|
||||
">
|
||||
<strong>Recommendation:</strong> ${win.recommendation}
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between; font-size: 10px; color: var(--vscode-text-dim);">
|
||||
<span>⏱️ ${win.estimate}</span>
|
||||
<span>📁 ${win.files_affected} files</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('ds-quick-wins-script', QuickWinsScript);
|
||||
Reference in New Issue
Block a user