Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>TokenCraft - Design System Studio</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <script src="https://cdn.tailwindcss.com"> | |
| </script> | |
| <style> | |
| :root { | |
| --grid-size: 8px; | |
| --base-font: 16px; | |
| --spacing-scale: 1; | |
| --shadow-opacity: 0.075; | |
| --font-family: system-ui, -apple-system, sans-serif; | |
| } | |
| body { | |
| font-family: var(--font-family); | |
| font-size: var(--base-font); | |
| } | |
| .preview-card { | |
| margin-bottom: calc(var(--grid-size) * var(--spacing-scale) * 2); | |
| padding: calc(var(--grid-size) * var(--spacing-scale) * 2); | |
| box-shadow: 0 calc(var(--grid-size) * 0.5) calc(var(--grid-size) * 1) rgba(0,0,0,var(--shadow-opacity)); | |
| } | |
| button, input, select { | |
| padding: calc(var(--grid-size) * var(--spacing-scale)) calc(var(--grid-size) * var(--spacing-scale) * 1.5); | |
| margin-bottom: calc(var(--grid-size) * var(--spacing-scale)); | |
| } | |
| .color-primary { | |
| background-color: var(--color-primary-600); | |
| border-color: var(--color-primary-500); | |
| color: var(--color-primary-600); | |
| } | |
| </style> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script> | |
| <style> | |
| .token-slider::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| appearance: none; | |
| width: 18px; | |
| height: 18px; | |
| border-radius: 50%; | |
| background: #4f46e5; | |
| cursor: pointer; | |
| } | |
| .preview-card { | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .grid-dot { | |
| background-image: radial-gradient(currentColor 1px, transparent 1px); | |
| background-size: var(--grid-size) var(--grid-size); | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 font-sans antialiased"> | |
| <!-- Vanta.js Background --> | |
| <div id="vanta-bg" class="fixed inset-0 -z-10 opacity-10"></div> | |
| <div class="min-h-screen"> | |
| <!-- Header --> | |
| <header class="bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50"> | |
| <div class="container mx-auto px-6 py-4"> | |
| <div class="flex items-center justify-between"> | |
| <div class="flex items-center space-x-2"> | |
| <i data-feather="box" class="text-indigo-600 w-6 h-6"></i> | |
| <h1 class="text-2xl font-bold text-gray-800">TokenCraft</h1> | |
| </div> | |
| <nav class="hidden md:flex space-x-8"> | |
| <a href="#" class="text-indigo-600 font-medium">Design Tokens</a> | |
| <a href="#" class="text-gray-600 hover:text-indigo-600 transition">Components</a> | |
| <a href="#" class="text-gray-600 hover:text-indigo-600 transition">Typography</a> | |
| <a href="#" class="text-gray-600 hover:text-indigo-600 transition">Export</a> | |
| </nav> | |
| <button class="md:hidden text-gray-600"> | |
| <i data-feather="menu"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <main class="container mx-auto px-6 py-8 grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
| <!-- Token Controls Panel --> | |
| <div class="lg:col-span-1 bg-white rounded-xl shadow-md p-6 sticky top-24 h-fit"> | |
| <div class="flex items-center justify-between mb-6"> | |
| <h2 class="text-xl font-bold text-gray-800">Design Tokens</h2> | |
| <button class="text-indigo-600 hover:text-indigo-800 transition"> | |
| <i data-feather="save" class="w-5 h-5"></i> | |
| </button> | |
| </div> | |
| <!-- Grid System Control --> | |
| <div class="mb-8"> | |
| <div class="flex items-center justify-between mb-3"> | |
| <h3 class="font-medium text-gray-700">Grid System</h3> | |
| <span class="text-sm font-mono bg-gray-100 px-2 py-1 rounded" id="grid-value">8px</span> | |
| </div> | |
| <input type="range" min="4" max="16" step="2" value="8" class="w-full token-slider" id="grid-slider"> | |
| <div class="flex justify-between text-xs text-gray-500 mt-1"> | |
| <span>4px</span> | |
| <span>8px</span> | |
| <span>12px</span> | |
| <span>16px</span> | |
| </div> | |
| </div> | |
| <!-- Color Palette --> | |
| <div class="mb-8"> | |
| <h3 class="font-medium text-gray-700 mb-3">Color Palette</h3> | |
| <div class="grid grid-cols-5 gap-2"> | |
| <div class="flex flex-col items-center"> | |
| <div class="w-8 h-8 rounded-full bg-indigo-500 mb-1 cursor-pointer hover:scale-110 transition" data-color="indigo"></div> | |
| <span class="text-xs">Primary</span> | |
| </div> | |
| <div class="flex flex-col items-center"> | |
| <div class="w-8 h-8 rounded-full bg-emerald-500 mb-1 cursor-pointer hover:scale-110 transition" data-color="emerald"></div> | |
| <span class="text-xs">Success</span> | |
| </div> | |
| <div class="flex flex-col items-center"> | |
| <div class="w-8 h-8 rounded-full bg-amber-500 mb-1 cursor-pointer hover:scale-110 transition" data-color="amber"></div> | |
| <span class="text-xs">Warning</span> | |
| </div> | |
| <div class="flex flex-col items-center"> | |
| <div class="w-8 h-8 rounded-full bg-rose-500 mb-1 cursor-pointer hover:scale-110 transition" data-color="rose"></div> | |
| <span class="text-xs">Danger</span> | |
| </div> | |
| <div class="flex flex-col items-center"> | |
| <div class="w-8 h-8 rounded-full bg-gray-500 mb-1 cursor-pointer hover:scale-110 transition" data-color="gray"></div> | |
| <span class="text-xs">Neutral</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Spacing Scale --> | |
| <div class="mb-8"> | |
| <h3 class="font-medium text-gray-700 mb-3">Spacing Scale</h3> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="block text-sm text-gray-600 mb-1">Base Unit</label> | |
| <div class="flex items-center space-x-2"> | |
| <input type="range" min="0.5" max="2" step="0.25" value="1" class="w-full token-slider" id="spacing-slider"> | |
| <span class="text-sm font-mono w-12 text-center" id="spacing-value">1x</span> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block text-sm text-gray-600 mb-1">Vertical Rhythm</label> | |
| <select class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm"> | |
| <option>8-point grid</option> | |
| <option selected>4-point grid</option> | |
| <option>Custom</option> | |
| </select> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Typography Scale --> | |
| <div class="mb-8"> | |
| <h3 class="font-medium text-gray-700 mb-3">Typography</h3> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="block text-sm text-gray-600 mb-1">Base Size</label> | |
| <div class="flex items-center space-x-2"> | |
| <input type="range" min="12" max="20" step="1" value="16" class="w-full token-slider" id="font-slider"> | |
| <span class="text-sm font-mono w-12 text-center" id="font-value">16px</span> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block text-sm text-gray-600 mb-1">Type Scale</label> | |
| <select class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm"> | |
| <option>Major Third (1.25)</option> | |
| <option selected>Perfect Fourth (1.333)</option> | |
| <option>Golden Ratio (1.618)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm text-gray-600 mb-1">Font Family</label> | |
| <select class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm"> | |
| <option>Inter (Sans-serif)</option> | |
| <option selected>System UI</option> | |
| <option>Georgia (Serif)</option> | |
| </select> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Shadow System --> | |
| <div> | |
| <h3 class="font-medium text-gray-700 mb-3">Shadows</h3> | |
| <div class="space-y-3"> | |
| <div class="flex items-center space-x-2"> | |
| <input type="checkbox" id="shadow-toggle" class="rounded text-indigo-600 focus:ring-indigo-500" checked> | |
| <label for="shadow-toggle" class="text-sm text-gray-600">Enable shadows</label> | |
| </div> | |
| <div> | |
| <label class="block text-sm text-gray-600 mb-1">Shadow Intensity</label> | |
| <input type="range" min="0" max="100" step="10" value="50" class="w-full token-slider" id="shadow-slider"> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Preview Panel --> | |
| <div class="lg:col-span-2 space-y-8"> | |
| <!-- Grid Visualization --> | |
| <div class="bg-white rounded-xl shadow-md p-6"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h2 class="text-lg font-medium text-gray-800">Grid System</h2> | |
| <div class="flex items-center space-x-2"> | |
| <button class="text-gray-500 hover:text-indigo-600 transition" id="grid-toggle"> | |
| <i data-feather="eye" class="w-4 h-4"></i> | |
| </button> | |
| <span class="text-xs font-mono bg-gray-100 px-2 py-1 rounded">8px baseline</span> | |
| </div> | |
| </div> | |
| <div class="grid-dot h-32 w-full border border-gray-200 rounded-md" style="--grid-size: 8px; color: rgba(0,0,0,0.05)"></div> | |
| </div> | |
| <!-- UI Components Preview --> | |
| <div class="bg-white rounded-xl shadow-md p-6"> | |
| <h2 class="text-lg font-medium text-gray-800 mb-6">Component Preview</h2> | |
| <!-- Buttons --> | |
| <div class="mb-8"> | |
| <h3 class="text-sm font-medium text-gray-700 mb-3">Buttons</h3> | |
| <div class="flex flex-wrap gap-3"> | |
| <button class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 transition">Primary</button> | |
| <button class="px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50 transition">Secondary</button> | |
| <button class="px-4 py-2 bg-emerald-500 text-white rounded-md hover:bg-emerald-600 transition">Success</button> | |
| <button class="px-4 py-2 bg-amber-500 text-white rounded-md hover:bg-amber-600 transition">Warning</button> | |
| <button class="px-4 py-2 bg-rose-500 text-white rounded-md hover:bg-rose-600 transition">Danger</button> | |
| </div> | |
| </div> | |
| <!-- Cards --> | |
| <div class="mb-8"> | |
| <h3 class="text-sm font-medium text-gray-700 mb-3">Cards</h3> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div class="preview-card border border-gray-200 rounded-lg overflow-hidden hover:shadow-md"> | |
| <div class="h-32 bg-indigo-100"></div> | |
| <div class="p-4"> | |
| <h4 class="font-medium mb-2">Default Card</h4> | |
| <p class="text-sm text-gray-600">This card demonstrates the current spacing and shadow settings.</p> | |
| </div> | |
| </div> | |
| <div class="preview-card border border-gray-200 rounded-lg overflow-hidden hover:shadow-md"> | |
| <div class="h-32 bg-emerald-100"></div> | |
| <div class="p-4"> | |
| <h4 class="font-medium mb-2">Another Card</h4> | |
| <p class="text-sm text-gray-600">All components update live as you adjust the design tokens.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Form Elements --> | |
| <div> | |
| <h3 class="text-sm font-medium text-gray-700 mb-3">Form Elements</h3> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Text Input</label> | |
| <input type="text" class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500" placeholder="Type something..."> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Select Menu</label> | |
| <select class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"> | |
| <option>Option 1</option> | |
| <option>Option 2</option> | |
| <option>Option 3</option> | |
| </select> | |
| </div> | |
| <div class="flex items-center space-x-3"> | |
| <div class="flex items-center"> | |
| <input id="push-everything" name="push-notifications" type="radio" class="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-500"> | |
| <label for="push-everything" class="ml-2 block text-sm text-gray-700">Radio 1</label> | |
| </div> | |
| <div class="flex items-center"> | |
| <input id="push-email" name="push-notifications" type="radio" class="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-500"> | |
| <label for="push-email" class="ml-2 block text-sm text-gray-700">Radio 2</label> | |
| </div> | |
| </div> | |
| <div class="flex items-center"> | |
| <input id="comments" name="comments" type="checkbox" class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"> | |
| <label for="comments" class="ml-2 block text-sm text-gray-700">Checkbox option</label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Typography Preview --> | |
| <div class="bg-white rounded-xl shadow-md p-6"> | |
| <h2 class="text-lg font-medium text-gray-800 mb-6">Typography</h2> | |
| <div class="space-y-4"> | |
| <h1 class="text-4xl font-bold">Heading 1</h1> | |
| <h2 class="text-3xl font-bold">Heading 2</h2> | |
| <h3 class="text-2xl font-bold">Heading 3</h3> | |
| <h4 class="text-xl font-bold">Heading 4</h4> | |
| <h5 class="text-lg font-bold">Heading 5</h5> | |
| <p class="text-base">Regular paragraph text. The quick brown fox jumps over the lazy dog.</p> | |
| <p class="text-sm">Smaller text for captions and secondary information.</p> | |
| <p class="text-xs">Very small text for meta information or labels.</p> | |
| <div class="pt-4 border-t border-gray-200"> | |
| <p class="font-mono text-sm bg-gray-50 p-2 rounded">Code: font-family: system-ui, -apple-system, sans-serif;</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <script> | |
| // Initialize Vanta.js background | |
| const vantaEffect = VANTA.NET({ | |
| el: "#vanta-bg", | |
| mouseControls: true, | |
| touchControls: true, | |
| gyroControls: false, | |
| minHeight: 200.00, | |
| minWidth: 200.00, | |
| scale: 1.00, | |
| scaleMobile: 1.00, | |
| color: 0x7c3aed, | |
| backgroundColor: 0xf9fafb, | |
| points: 10.00, | |
| maxDistance: 20.00 | |
| }); | |
| // Initialize Feather Icons | |
| feather.replace(); | |
| // Design Token Store | |
| const designTokens = { | |
| grid: 8, | |
| color: 'indigo', | |
| spacing: 1, | |
| font: 16, | |
| shadow: true, | |
| shadowIntensity: 50, | |
| typeScale: 'Perfect Fourth (1.333)', | |
| fontFamily: 'System UI' | |
| }; | |
| // Utility function to update CSS variables | |
| function updateCSSVariables() { | |
| const root = document.documentElement; | |
| root.style.setProperty('--grid-size', `${designTokens.grid}px`); | |
| root.style.setProperty('--base-font', `${designTokens.font}px`); | |
| root.style.setProperty('--spacing-scale', designTokens.spacing); | |
| // Update shadows | |
| const shadowOpacity = designTokens.shadow ? (designTokens.shadowIntensity / 100) * 0.15 : 0; | |
| root.style.setProperty('--shadow-opacity', shadowOpacity); | |
| // Update color scheme | |
| document.querySelectorAll('.color-primary').forEach(el => { | |
| el.classList.remove(`bg-${designTokens.color}-600`, `border-${designTokens.color}-500`, `text-${designTokens.color}-600`); | |
| el.classList.add(`bg-${designTokens.color}-600`, `border-${designTokens.color}-500`, `text-${designTokens.color}-600`); | |
| }); | |
| // Update font family | |
| if (designTokens.fontFamily === 'System UI') { | |
| root.style.setProperty('--font-family', 'system-ui, -apple-system, sans-serif'); | |
| } else if (designTokens.fontFamily === 'Inter (Sans-serif)') { | |
| root.style.setProperty('--font-family', '"Inter", sans-serif'); | |
| if (!document.querySelector('#inter-font')) { | |
| const link = document.createElement('link'); | |
| link.id = 'inter-font'; | |
| link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap'; | |
| link.rel = 'stylesheet'; | |
| document.head.appendChild(link); | |
| } | |
| } else if (designTokens.fontFamily === 'Georgia (Serif)') { | |
| root.style.setProperty('--font-family', 'Georgia, serif'); | |
| } | |
| } | |
| // Grid System Controls | |
| const gridSlider = document.getElementById('grid-slider'); | |
| const gridValue = document.getElementById('grid-value'); | |
| const gridToggle = document.getElementById('grid-toggle'); | |
| const gridDot = document.querySelector('.grid-dot'); | |
| gridSlider.addEventListener('input', function() { | |
| designTokens.grid = parseInt(this.value); | |
| gridValue.textContent = `${designTokens.grid}px`; | |
| updateCSSVariables(); | |
| }); | |
| gridToggle.addEventListener('click', function() { | |
| const currentColor = gridDot.style.color; | |
| gridDot.style.color = currentColor === 'rgba(0,0,0,0.05)' ? 'transparent' : 'rgba(0,0,0,0.05)'; | |
| const icon = this.querySelector('i'); | |
| if (icon.dataset.feather === 'eye') { | |
| icon.dataset.feather = 'eye-off'; | |
| } else { | |
| icon.dataset.feather = 'eye'; | |
| } | |
| feather.replace(); | |
| }); | |
| // Color Palette Selection | |
| document.querySelectorAll('[data-color]').forEach(swatch => { | |
| swatch.addEventListener('click', function() { | |
| designTokens.color = this.dataset.color; | |
| updateCSSVariables(); | |
| // Update all elements with color classes | |
| document.querySelectorAll('[class*="bg-"], [class*="text-"], [class*="border-"]').forEach(el => { | |
| const classes = Array.from(el.classList); | |
| classes.forEach(cls => { | |
| if (cls.includes('bg-') || cls.includes('text-') || cls.includes('border-')) { | |
| if (cls.includes('indigo') || cls.includes('emerald') || cls.includes('amber') || cls.includes('rose') || cls.includes('gray')) { | |
| const newClass = cls.replace(/(indigo|emerald|amber|rose|gray)/g, designTokens.color); | |
| el.classList.remove(cls); | |
| el.classList.add(newClass); | |
| } | |
| } | |
| }); | |
| }); | |
| }); | |
| }); | |
| // Spacing Controls | |
| const spacingSlider = document.getElementById('spacing-slider'); | |
| const spacingValue = document.getElementById('spacing-value'); | |
| spacingSlider.addEventListener('input', function() { | |
| designTokens.spacing = parseFloat(this.value); | |
| spacingValue.textContent = `${designTokens.spacing}x`; | |
| updateCSSVariables(); | |
| // Update preview cards and other components with spacing | |
| document.querySelectorAll('.preview-card, button, input, select').forEach(el => { | |
| const basePadding = 8 * designTokens.spacing; | |
| el.style.padding = `${basePadding}px ${basePadding * 1.5}px`; | |
| el.style.marginBottom = `${basePadding}px`; | |
| }); | |
| }); | |
| // Font Controls | |
| const fontSlider = document.getElementById('font-slider'); | |
| const fontValue = document.getElementById('font-value'); | |
| fontSlider.addEventListener('input', function() { | |
| designTokens.font = parseInt(this.value); | |
| fontValue.textContent = `${designTokens.font}px`; | |
| updateCSSVariables(); | |
| // Update all text elements with new font size | |
| document.querySelectorAll('h1, h2, h3, h4, h5, p, button, input, select').forEach(el => { | |
| if (el.tagName.startsWith('H')) { | |
| const level = parseInt(el.tagName[1]); | |
| const scale = Math.pow(1.333, 5 - level); // Perfect Fourth scale | |
| el.style.fontSize = `${designTokens.font * scale}px`; | |
| } else if (el.tagName === 'P') { | |
| el.style.fontSize = `${designTokens.font}px`; | |
| } | |
| }); | |
| }); | |
| // Type Scale Control | |
| document.querySelectorAll('select')[0].addEventListener('change', function() { | |
| designTokens.typeScale = this.value; | |
| updateCSSVariables(); | |
| // Trigger font size update | |
| fontSlider.dispatchEvent(new Event('input')); | |
| }); | |
| // Font Family Control | |
| document.querySelectorAll('select')[1].addEventListener('change', function() { | |
| designTokens.fontFamily = this.value; | |
| updateCSSVariables(); | |
| // Update all text elements with new font family | |
| document.querySelectorAll('h1, h2, h3, h4, h5, p, button, input, select').forEach(el => { | |
| if (designTokens.fontFamily === 'System UI') { | |
| el.style.fontFamily = 'system-ui, -apple-system, sans-serif'; | |
| } else if (designTokens.fontFamily === 'Inter (Sans-serif)') { | |
| el.style.fontFamily = '"Inter", sans-serif'; | |
| } else if (designTokens.fontFamily === 'Georgia (Serif)') { | |
| el.style.fontFamily = 'Georgia, serif'; | |
| } | |
| }); | |
| }); | |
| // Shadow Controls | |
| const shadowSlider = document.getElementById('shadow-slider'); | |
| const shadowToggle = document.getElementById('shadow-toggle'); | |
| shadowSlider.addEventListener('input', function() { | |
| designTokens.shadowIntensity = parseInt(this.value); | |
| updateCSSVariables(); | |
| // Update shadow on all elements | |
| const shadowOpacity = designTokens.shadow ? (designTokens.shadowIntensity / 100) * 0.15 : 0; | |
| document.querySelectorAll('.preview-card, button, .rounded-xl').forEach(el => { | |
| if (designTokens.shadow) { | |
| el.style.boxShadow = `0 ${designTokens.grid * 0.5}px ${designTokens.grid * 1}px rgba(0,0,0,${shadowOpacity})`; | |
| } else { | |
| el.style.boxShadow = 'none'; | |
| } | |
| }); | |
| }); | |
| shadowToggle.addEventListener('change', function() { | |
| designTokens.shadow = this.checked; | |
| updateCSSVariables(); | |
| // Trigger shadow update | |
| shadowSlider.dispatchEvent(new Event('input')); | |
| }); | |
| // Save Button | |
| document.querySelector('[data-feather="save"]').parentElement.addEventListener('click', function() { | |
| const dataStr = JSON.stringify(designTokens, null, 2); | |
| const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr); | |
| const exportName = `tokencraft-${new Date().toISOString().slice(0,10)}.json`; | |
| const linkElement = document.createElement('a'); | |
| linkElement.setAttribute('href', dataUri); | |
| linkElement.setAttribute('download', exportName); | |
| linkElement.click(); | |
| // Show temporary feedback | |
| const icon = this.querySelector('i'); | |
| const originalIcon = icon.dataset.feather; | |
| icon.dataset.feather = 'check'; | |
| feather.replace(); | |
| setTimeout(() => { | |
| icon.dataset.feather = originalIcon; | |
| feather.replace(); | |
| }, 2000); | |
| }); | |
| // Initialize with current values | |
| updateCSSVariables(); | |
| // Add initial event triggers to set up the UI correctly | |
| setTimeout(() => { | |
| fontSlider.dispatchEvent(new Event('input')); | |
| spacingSlider.dispatchEvent(new Event('input')); | |
| shadowSlider.dispatchEvent(new Event('input')); | |
| }, 100); | |
| </script> | |
| </body> | |
| </html> | |