🎨
SkyeUI Pro
Upgrade Studio v2.0
📂 Load HTML

Drop HTML file here

or click to browse
🎨 Theme Preset

Sharp10pxRounded
Actions
👁 Live Preview No file loaded

Load an HTML file to preview

💉Injected CSSLive
🎨Design Tokens

Edit tokens below — preview updates live.




👁Token PreviewLive
🤖Brand Prompt

Describe your brand or desired aesthetic and the AI will generate a full CSS theme.


🎨Generated ThemeWaiting…
/* Your generated CSS theme will appear here */

🖌 Themed HTML File

Ready

Download the full HTML from the Reskin Studio with your chosen theme injected.

🎨 CSS Theme File

Custom

Export just the generated CSS — drop into any project.

/* CSS will appear here after applying a theme */

📦 Token JSON

Export your current design tokens as a JSON config file.

{}

🔤 CSS Variables

Export tokens as :root CSS custom properties.

:root {}
SkyeUI Pro
|
Theme: None
|
No file loaded
|
kAIxU Gateway

Neural Space Pro

`; } else if (mode === 'dark-override') { out = rawHTML.replace('', `\n`); } themedHTML = out; document.getElementById('injected-css-view').value = css; setPreview(out); toast('Theme applied — ' + THEMES[selectedTheme].name, 'success'); BC.postMessage({type:'log',msg:`[SkyeUI Pro] Applied theme: ${THEMES[selectedTheme].name}`}); } function setPreview(html) { const iframe = document.getElementById('preview-iframe'); const empty = document.getElementById('preview-empty'); iframe.style.display = 'block'; empty.style.display = 'none'; iframe.srcdoc = html; document.getElementById('preview-status').textContent = 'Preview active'; document.getElementById('sb-file').textContent = 'File loaded'; } function resetPreview() { if (!rawHTML) return; setPreview(rawHTML); themedHTML = ''; currentCSS = ''; document.getElementById('injected-css-view').value = ''; document.getElementById('preview-status').textContent = 'Original'; toast('Preview reset to original', 'info'); } function loadFile(file) { if (!file) return; const r = new FileReader(); r.onload = e => { rawHTML = e.target.result; document.getElementById('sb-file').textContent = file.name; document.getElementById('preview-status').textContent = 'Loaded'; setPreview(rawHTML); toast('Loaded: ' + file.name, 'success'); }; r.readAsText(file); } function loadPasted() { const v = document.getElementById('paste-html').value.trim(); if (!v) { toast('Paste some HTML first', 'error'); return; } rawHTML = v; document.getElementById('sb-file').textContent = 'Pasted HTML'; setPreview(rawHTML); toast('HTML loaded from paste', 'success'); } // Drag & drop const dz = document.getElementById('drop-zone'); document.getElementById('file-in').addEventListener('change', e => loadFile(e.target.files[0])); dz.addEventListener('dragover', e => { e.preventDefault(); dz.classList.add('drag-over'); }); dz.addEventListener('dragleave', () => dz.classList.remove('drag-over')); dz.addEventListener('drop', e => { e.preventDefault(); dz.classList.remove('drag-over'); loadFile(e.dataTransfer.files[0]); }); function copyOutput() { const out = themedHTML || rawHTML; if (!out) { toast('Nothing to copy', 'error'); return; } navigator.clipboard.writeText(out); toast('Copied to clipboard', 'success'); } function downloadThemed() { const out = themedHTML || rawHTML; if (!out) { toast('Nothing to download — apply a theme first', 'error'); return; } dl(out, 'themed-output.html', 'text/html'); } function downloadCSS() { const css = currentCSS || aiGeneratedCSS; if (!css) { toast('No CSS generated yet', 'error'); return; } dl(css, 'skyeui-theme.css', 'text/css'); } // ══════════════════════════════════════════════ // TOKEN EDITOR // ══════════════════════════════════════════════ const DEFAULT_TOKENS = { '--bg': '#07040d', '--surface': '#0f0a1a', '--surface2': '#160d25', '--border': '#2a1f45', '--accent': '#7c3aed', '--accent2': '#a855f7', '--gold': '#fbbf24', '--text': '#e2d9f3', '--text2': '#9d8fc0', '--red': '#fb7185', '--green': '#34d399', '--cyan': '#06b6d4' }; const TOKEN_LABELS = { '--bg': 'Background', '--surface': 'Surface', '--surface2': 'Surface 2', '--border': 'Border', '--accent': 'Accent', '--accent2': 'Accent 2', '--gold': 'Gold', '--text': 'Text', '--text2': 'Text Muted', '--red': 'Danger', '--green': 'Success', '--cyan': 'Info' }; let tokens = {...DEFAULT_TOKENS}; function buildTokenEditor() { const container = document.getElementById('color-tokens'); container.innerHTML = Object.entries(tokens).map(([k, v]) => `
`).join(''); } function tokenChanged(k, v) { tokens[k] = v; document.getElementById('toktext' + k).value = v; updateTokenPreview(); } function tokenTextChanged(k, v) { if (/^#[0-9a-fA-F]{6}$/.test(v)) { tokens[k] = v; document.getElementById('tok' + k).value = v; updateTokenPreview(); } } document.getElementById('tok-radius').addEventListener('input', function() { document.getElementById('tok-radius-label').textContent = this.value + 'px'; updateTokenPreview(); }); function getTokenCSS() { const r = document.getElementById('tok-radius').value; return `:root{${Object.entries(tokens).map(([k,v]) => `${k}:${v}`).join(';')};--radius:${r}px}`; } function updateTokenPreview() { const wrap = document.getElementById('token-preview-wrap'); const r = document.getElementById('tok-radius').value; wrap.style.cssText = Object.entries(tokens).map(([k,v]) => `${k}:${v}`).join(';') + `;--radius:${r}px`; wrap.style.background = tokens['--surface'] || '#0f0a1a'; wrap.style.borderColor = tokens['--border'] || '#2a1f45'; renderLiveComponents(); } function renderLiveComponents() { const c = document.getElementById('live-preview-components'); const t = tokens; c.innerHTML = `
Buttons
Badges
Purple Gold Success Error
Card
Card Title
This is a preview card component showing your current token values applied in real-time.
Inputs
`; } function applyTokens() { updateTokenPreview(); toast('Tokens applied to preview', 'success'); } function resetTokens() { tokens = {...DEFAULT_TOKENS}; document.getElementById('tok-radius').value = 10; document.getElementById('tok-radius-label').textContent = '10px'; buildTokenEditor(); updateTokenPreview(); toast('Tokens reset to defaults', 'info'); } function exportTokensCSS() { const css = getTokenCSS(); dl(css, 'skyeui-tokens.css', 'text/css'); toast('CSS vars exported', 'success'); } function exportTokensJSON() { const r = document.getElementById('tok-radius').value; const json = JSON.stringify({...tokens, '--radius': r + 'px'}, null, 2); dl(json, 'skyeui-tokens.json', 'application/json'); toast('Token JSON exported', 'success'); } // ══════════════════════════════════════════════ // COMPONENT LIBRARY // ══════════════════════════════════════════════ const COMPONENT_DEFS = [ { name: 'Buttons', category: 'Basics', render: () => ` ` }, { name: 'Badges', category: 'Basics', render: () => ` ACTIVE GOLD ✓ SUCCESS ERROR INFO ` }, { name: 'Glass Card', category: 'Layout', render: () => `
Card Title
A glass-morphism panel card with dark surface, border, and backdrop blur.
` }, { name: 'Stat Cards', category: 'Data', render: () => `
${[['Total Revenue','$124,850','↑ 12.4%','#fbbf24'],['Active Users','8,291','↑ 3.1%','#34d399'],['Error Rate','0.02%','↓ 0.5%','#fb7185']].map(([l,v,d,c]) => `
${l}
${v}
${d}
`).join('')}
` }, { name: 'Input Group', category: 'Forms', render: () => `
` }, { name: 'Navbar', category: 'Layout', render: () => `
BRAND
Home Docs Pricing
` }, { name: 'Progress Bars', category: 'Data', render: () => `
${[['Revenue','78%','#7c3aed'],['Conversion','52%','#fbbf24'],['Uptime','99%','#34d399']].map(([l,p,c]) => `
${l} ${p}
`).join('')}
` }, { name: 'Alert / Banner', category: 'Feedback', render: () => `
✓ Operation completed successfully
⚠ Your API key expires in 3 days
✕ Failed to connect to gateway
` }, { name: 'Avatar Group', category: 'Basics', render: () => `
${['#7c3aed','#0ea5e9','#fbbf24','#34d399','#ec4899'].map((c,i) => `
${'ABCDE'[i]}
`).join('')}
+24 members
` }, { name: 'Toggle / Switch', category: 'Forms', render: () => `
${[['Dark Mode',true],['Notifications',false],['Analytics',true]].map(([l,on]) => `
${l}
`).join('')}
` }, { name: 'Code Block', category: 'Content', render: () => `
main.js
const theme = applyTheme('purple-gold');
await theme.inject({ radius: 10 });
` }, { name: 'Data Table', category: 'Data', render: () => `
${['Name','Status','Revenue','Actions'].map(h=>``).join('')} ${[['Acme Corp','Active','$48,200'],['Nova Labs','Paused','$12,800'],['Skyex Inc','Active','$91,450']].map(([n,s,r])=>` `).join('')}
${h}
${n} ${s} ${r}
` } ]; const COMP_CATEGORIES = [...new Set(COMPONENT_DEFS.map(c => c.category))]; let activeFilter = 'All'; let searchQ = ''; function buildCompFilters() { const f = document.getElementById('comp-filters'); f.innerHTML = ['All', ...COMP_CATEGORIES].map(cat => ` `).join(''); } function setFilter(cat) { activeFilter = cat; document.querySelectorAll('.filter-chip').forEach(c => c.classList.remove('active')); [...document.querySelectorAll('.filter-chip')].find(c => c.textContent === cat)?.classList.add('active'); renderComps(); } function filterComps() { searchQ = document.getElementById('comp-search').value.toLowerCase(); renderComps(); } function renderComps() { const grid = document.getElementById('comp-grid'); const filtered = COMPONENT_DEFS.filter(c => { const matchFilter = activeFilter === 'All' || c.category === activeFilter; const matchSearch = !searchQ || c.name.toLowerCase().includes(searchQ) || c.category.toLowerCase().includes(searchQ); return matchFilter && matchSearch; }); grid.innerHTML = filtered.map(c => `
${c.name} ${c.category}
${c.render()}
`).join(''); if (!filtered.length) grid.innerHTML = '
No components match your search
'; } function copyCompHTML(html) { navigator.clipboard.writeText(html.trim()); toast('HTML copied', 'success'); } // ══════════════════════════════════════════════ // AI THEMING // ══════════════════════════════════════════════ function quickPrompt(p) { document.getElementById('ai-prompt').value = p; sendAITheme(); } async function sendAITheme() { const prompt = document.getElementById('ai-prompt').value.trim(); if (!prompt) { toast('Enter a brand description', 'error'); return; } addAIMsg('user', prompt); document.getElementById('ai-prompt').value = ''; document.getElementById('ai-status').textContent = 'Generating…'; const thinking = addAIMsg('ai', '
'); try { const body = { messages: [ { role: 'system', content: 'You are a world-class CSS theme designer. The user describes a brand/aesthetic and you return ONLY a valid CSS block as plain text (no markdown code fences, no explanation). Include :root variables for --bg, --surface, --surface2, --border, --accent, --accent2, --gold, --text, --text2, --radius, and general body, button, input styles. Make it production-quality.' }, { role: 'user', content: `Generate a CSS theme for: ${prompt}` } ] }; const res = await fetch(GW, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); const data = await res.json(); const css = data.choices?.[0]?.message?.content || '/* No response */'; aiGeneratedCSS = css; thinking.remove(); addAIMsg('ai', '✓ Theme generated — see panel →'); document.getElementById('ai-result').textContent = css; document.getElementById('ai-status').textContent = 'Ready'; toast('AI theme generated', 'success'); } catch(e) { thinking.remove(); addAIMsg('ai', '✕ Error: ' + e.message); document.getElementById('ai-status').textContent = 'Error'; toast('AI request failed', 'error'); } } function addAIMsg(role, html) { const el = document.createElement('div'); el.className = 'ai-msg ' + role; el.innerHTML = html; document.getElementById('ai-messages').appendChild(el); el.scrollIntoView({block:'end'}); return el; } function applyAITheme() { if (!aiGeneratedCSS) { toast('Generate a theme first', 'error'); return; } currentCSS = aiGeneratedCSS; if (rawHTML) { themedHTML = rawHTML.replace('', `\n`); setPreview(themedHTML); } document.getElementById('injected-css-view').value = aiGeneratedCSS; toast('AI theme applied', 'success'); } function copyAITheme() { if (!aiGeneratedCSS) { toast('No theme yet', 'error'); return; } navigator.clipboard.writeText(aiGeneratedCSS); toast('CSS copied', 'success'); } function downloadAITheme() { if (!aiGeneratedCSS) { toast('No theme yet', 'error'); return; } dl(aiGeneratedCSS, 'ai-theme.css', 'text/css'); } // ══════════════════════════════════════════════ // EXPORT PREVIEWS // ══════════════════════════════════════════════ function refreshExportPreviews() { const html = themedHTML || rawHTML || ''; document.getElementById('export-html-preview').textContent = html ? html.slice(0, 300) + (html.length > 300 ? '…' : '') : '(no file loaded)'; const css = currentCSS || aiGeneratedCSS || ''; document.getElementById('export-css-preview').textContent = css ? css.slice(0, 300) + (css.length > 300 ? '…' : '') : '/* no theme generated */'; const r = document.getElementById('tok-radius').value; const json = JSON.stringify({...tokens, '--radius': r + 'px'}, null, 2); document.getElementById('export-json-preview').textContent = json; const vars = getTokenCSS(); document.getElementById('export-vars-preview').textContent = vars; } // ══════════════════════════════════════════════ // NSP CHAT // ══════════════════════════════════════════════ function toggleNSP() { document.getElementById('nsp-panel').classList.toggle('open'); } function nspKey(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); nspSend(); } } async function nspSend() { const inp = document.getElementById('nsp-input'); const msg = inp.value.trim(); if (!msg) return; inp.value = ''; nspMsg('user', msg); const think = nspMsg('ai', '
'); try { const r = await fetch(GW, { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({messages:[{role:'system',content:'You are kAIxU, an expert design systems assistant in SkyeUI Pro. Help with CSS theming, component design, and HTML injection.'},{role:'user',content:msg}]}) }); const d = await r.json(); think.remove(); nspMsg('ai', d.choices?.[0]?.message?.content || 'No response'); } catch(e) { think.remove(); nspMsg('ai', 'Error: ' + e.message); } } function nspMsg(role, html) { const el = document.createElement('div'); el.className = 'nsp-msg ' + role; el.innerHTML = html; const msgs = document.getElementById('nsp-messages'); msgs.appendChild(el); msgs.scrollTop = msgs.scrollHeight; return el; } // ══════════════════════════════════════════════ // UTILS // ══════════════════════════════════════════════ function toast(msg, type='info') { const el = document.createElement('div'); el.className = 'toast ' + type; el.textContent = msg; document.getElementById('toast-area').appendChild(el); setTimeout(() => el.remove(), 3200); } function dl(content, name, type) { const a = document.createElement('a'); a.href = URL.createObjectURL(new Blob([content], {type})); a.download = name; a.click(); } // ══════════════════════════════════════════════ // INIT // ══════════════════════════════════════════════ buildThemeGrid(); buildTokenEditor(); updateTokenPreview(); buildCompFilters(); renderComps(); // PWA if ('serviceWorker' in navigator) { navigator.serviceWorker.register('./service-worker.js').catch(() => {}); }