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
198 lines
7.4 KiB
JavaScript
198 lines
7.4 KiB
JavaScript
/**
|
|
* ds-token-list.js
|
|
* Design token listing and management
|
|
* View, edit, and validate design tokens
|
|
*/
|
|
|
|
import contextStore from '../../stores/context-store.js';
|
|
|
|
export default class TokenList extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.tokens = [
|
|
{ id: 'color-primary', name: 'Primary Color', category: 'Colors', value: '#0066CC', usage: 156 },
|
|
{ id: 'color-success', name: 'Success Color', category: 'Colors', value: '#4caf50', usage: 89 },
|
|
{ id: 'color-error', name: 'Error Color', category: 'Colors', value: '#f44336', usage: 76 },
|
|
{ id: 'color-warning', name: 'Warning Color', category: 'Colors', value: '#ff9800', usage: 54 },
|
|
{ id: 'spacing-xs', name: 'Extra Small Spacing', category: 'Spacing', value: '4px', usage: 234 },
|
|
{ id: 'spacing-sm', name: 'Small Spacing', category: 'Spacing', value: '8px', usage: 312 },
|
|
{ id: 'spacing-md', name: 'Medium Spacing', category: 'Spacing', value: '16px', usage: 445 },
|
|
{ id: 'spacing-lg', name: 'Large Spacing', category: 'Spacing', value: '24px', usage: 198 },
|
|
{ id: 'font-body', name: 'Body Font', category: 'Typography', value: 'Inter, sans-serif', usage: 678 },
|
|
{ id: 'font-heading', name: 'Heading Font', category: 'Typography', value: 'Poppins, sans-serif', usage: 234 },
|
|
];
|
|
this.selectedCategory = 'All';
|
|
this.editingTokenId = null;
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.render();
|
|
this.setupEventListeners();
|
|
}
|
|
|
|
render() {
|
|
this.innerHTML = `
|
|
<div style="padding: 24px; height: 100%; overflow-y: auto;">
|
|
<div style="margin-bottom: 24px; display: flex; justify-content: space-between; align-items: start;">
|
|
<div>
|
|
<h1 style="margin: 0 0 8px 0; font-size: 24px;">Design Tokens</h1>
|
|
<p style="margin: 0; color: var(--vscode-text-dim);">
|
|
Manage and track design token usage across the system
|
|
</p>
|
|
</div>
|
|
<button id="export-btn" style="
|
|
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;
|
|
">⬇️ Export Tokens</button>
|
|
</div>
|
|
|
|
<!-- Category Filter -->
|
|
<div style="margin-bottom: 24px; display: flex; gap: 8px; flex-wrap: wrap;">
|
|
${['All', 'Colors', 'Spacing', 'Typography', 'Shadows', 'Borders'].map(cat => `
|
|
<button class="filter-btn" data-category="${cat}" style="
|
|
padding: 6px 12px;
|
|
background: ${this.selectedCategory === cat ? 'var(--vscode-selection)' : 'var(--vscode-sidebar)'};
|
|
color: var(--vscode-foreground);
|
|
border: 1px solid ${this.selectedCategory === cat ? 'var(--vscode-focusBorder)' : 'var(--vscode-border)'};
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
">${cat}</button>
|
|
`).join('')}
|
|
</div>
|
|
|
|
<!-- Token Table -->
|
|
<div style="background: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; overflow: hidden;">
|
|
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 0.8fr 0.8fr; gap: 0; font-size: 11px; font-weight: 600; background: var(--vscode-bg); border-bottom: 1px solid var(--vscode-border); padding: 12px; color: var(--vscode-text-dim); text-transform: uppercase; letter-spacing: 0.5px;">
|
|
<div>Token Name</div>
|
|
<div>Category</div>
|
|
<div>Value</div>
|
|
<div>Usage</div>
|
|
<div>Actions</div>
|
|
</div>
|
|
|
|
<div id="tokens-container" style="max-height: 500px; overflow-y: auto;">
|
|
${this.renderTokenRows()}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
renderTokenRows() {
|
|
const filtered = this.selectedCategory === 'All'
|
|
? this.tokens
|
|
: this.tokens.filter(t => t.category === this.selectedCategory);
|
|
|
|
return filtered.map(token => `
|
|
<div style="
|
|
display: grid;
|
|
grid-template-columns: 2fr 1fr 1fr 0.8fr 0.8fr;
|
|
gap: 0;
|
|
align-items: center;
|
|
padding: 12px;
|
|
border-bottom: 1px solid var(--vscode-border);
|
|
font-size: 12px;
|
|
">
|
|
<div>
|
|
<div style="font-weight: 500; margin-bottom: 2px;">${token.name}</div>
|
|
<div style="font-size: 10px; color: var(--vscode-text-dim); font-family: monospace;">
|
|
${token.id}
|
|
</div>
|
|
</div>
|
|
<div style="color: var(--vscode-text-dim); font-size: 11px;">
|
|
${token.category}
|
|
</div>
|
|
<div style="font-family: monospace; background: var(--vscode-bg); padding: 4px 6px; border-radius: 2px;">
|
|
${token.value}
|
|
</div>
|
|
<div style="text-align: center; color: var(--vscode-text-dim);">
|
|
${token.usage}
|
|
</div>
|
|
<div style="display: flex; gap: 4px;">
|
|
<button class="edit-token-btn" data-token-id="${token.id}" style="
|
|
padding: 3px 8px;
|
|
background: var(--vscode-button-secondaryBackground);
|
|
color: var(--vscode-button-secondaryForeground);
|
|
border: none;
|
|
border-radius: 2px;
|
|
cursor: pointer;
|
|
font-size: 10px;
|
|
">Edit</button>
|
|
<button class="copy-token-btn" data-token-value="${token.value}" style="
|
|
padding: 3px 8px;
|
|
background: var(--vscode-button-secondaryBackground);
|
|
color: var(--vscode-button-secondaryForeground);
|
|
border: none;
|
|
border-radius: 2px;
|
|
cursor: pointer;
|
|
font-size: 10px;
|
|
">Copy</button>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
setupEventListeners() {
|
|
// Filter buttons
|
|
this.querySelectorAll('.filter-btn').forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
this.selectedCategory = btn.dataset.category;
|
|
this.render();
|
|
this.setupEventListeners();
|
|
});
|
|
});
|
|
|
|
// Export button
|
|
const exportBtn = this.querySelector('#export-btn');
|
|
if (exportBtn) {
|
|
exportBtn.addEventListener('click', () => {
|
|
const tokenData = JSON.stringify(this.tokens, null, 2);
|
|
const blob = new Blob([tokenData], { type: 'application/json' });
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = 'design-tokens.json';
|
|
a.click();
|
|
URL.revokeObjectURL(url);
|
|
});
|
|
}
|
|
|
|
// Edit token buttons
|
|
this.querySelectorAll('.edit-token-btn').forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
const tokenId = btn.dataset.tokenId;
|
|
const token = this.tokens.find(t => t.id === tokenId);
|
|
this.dispatchEvent(new CustomEvent('edit-token', {
|
|
detail: { token },
|
|
bubbles: true,
|
|
composed: true
|
|
}));
|
|
});
|
|
});
|
|
|
|
// Copy token buttons
|
|
this.querySelectorAll('.copy-token-btn').forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
const value = btn.dataset.tokenValue;
|
|
navigator.clipboard.writeText(value).then(() => {
|
|
const originalText = btn.textContent;
|
|
btn.textContent = '✓ Copied';
|
|
setTimeout(() => {
|
|
btn.textContent = originalText;
|
|
}, 1500);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
customElements.define('ds-token-list', TokenList);
|