mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-14 15:16:35 +03:00
better demos
This commit is contained in:
+165
-7
@@ -28,16 +28,35 @@
|
||||
.command-manual {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-lg);
|
||||
gap: var(--spacing-sm);
|
||||
padding-bottom: 20vh;
|
||||
}
|
||||
|
||||
.command-category-header {
|
||||
font-family: var(--font-display);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-accent);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
padding: var(--spacing-lg) var(--spacing-lg) var(--spacing-sm);
|
||||
margin-top: var(--spacing-md);
|
||||
border-bottom: 1px solid var(--color-mist);
|
||||
}
|
||||
|
||||
.command-category-header:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.manual-entry {
|
||||
position: relative;
|
||||
padding: var(--spacing-lg);
|
||||
padding-left: calc(var(--spacing-lg) + 16px); /* Reserve space for transform */
|
||||
border-left: 2px solid var(--color-mist);
|
||||
transition: all 0.4s var(--ease-out);
|
||||
transition: border-color 0.4s var(--ease-out), opacity 0.4s var(--ease-out), background 0.4s var(--ease-out), transform 0.4s var(--ease-out);
|
||||
opacity: 0.4;
|
||||
cursor: pointer;
|
||||
transform: translateX(-16px);
|
||||
}
|
||||
|
||||
.manual-entry:hover {
|
||||
@@ -47,7 +66,7 @@
|
||||
.manual-entry.active {
|
||||
border-left-color: var(--color-accent);
|
||||
opacity: 1;
|
||||
padding-left: var(--spacing-xl);
|
||||
transform: translateX(0);
|
||||
background: linear-gradient(to right, var(--color-bg), transparent);
|
||||
}
|
||||
|
||||
@@ -66,11 +85,38 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.manual-cmd-rel {
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-ash);
|
||||
margin-top: var(--spacing-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5ch;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.manual-cmd-rel .rel-icon {
|
||||
color: var(--color-accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.manual-cmd-rel code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
background: var(--color-mist);
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
/* Right: The Terminal (Sticky) */
|
||||
.glass-terminal-wrapper {
|
||||
position: sticky;
|
||||
top: var(--spacing-lg);
|
||||
height: 600px;
|
||||
bottom: var(--spacing-lg);
|
||||
height: calc(100vh - var(--spacing-lg) * 2);
|
||||
max-height: 800px;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
@@ -123,13 +169,14 @@
|
||||
|
||||
.terminal-body {
|
||||
flex: 1;
|
||||
padding: var(--spacing-lg);
|
||||
padding: var(--spacing-md);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.9375rem;
|
||||
color: var(--color-ink);
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0; /* Allow flex shrinking */
|
||||
}
|
||||
|
||||
.terminal-line {
|
||||
@@ -160,14 +207,125 @@
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* Hide steps when viewport is short */
|
||||
@media (max-height: 800px) {
|
||||
.terminal-output {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.terminal-cmd {
|
||||
color: var(--color-accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.terminal-step {
|
||||
color: var(--color-charcoal);
|
||||
}
|
||||
|
||||
.terminal-done {
|
||||
color: var(--color-success, #22c55e);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.terminal-preview {
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 4px;
|
||||
background: var(--color-paper);
|
||||
padding: var(--spacing-md);
|
||||
margin: var(--spacing-md) 0;
|
||||
margin: var(--spacing-sm) 0;
|
||||
flex: 1;
|
||||
min-height: 0; /* Allow shrinking */
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.terminal-cursor-line {
|
||||
flex-shrink: 0;
|
||||
margin-top: var(--spacing-sm) !important;
|
||||
}
|
||||
|
||||
.terminal-preview .demo-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.terminal-preview .demo-header {
|
||||
flex-shrink: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.terminal-preview .demo-viewport {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding: var(--spacing-md);
|
||||
min-height: 0;
|
||||
max-height: 320px;
|
||||
overflow: auto;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.terminal-preview .demo-viewport > * {
|
||||
margin-block: auto; /* Center vertically when content is shorter than container */
|
||||
}
|
||||
|
||||
.terminal-preview .demo-caption {
|
||||
flex-shrink: 0;
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-ash);
|
||||
text-align: center;
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
}
|
||||
|
||||
/* Demo toggle in terminal */
|
||||
.terminal-preview .demo-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.terminal-preview .demo-toggle-switch {
|
||||
width: 36px;
|
||||
height: 20px;
|
||||
background: var(--color-mist);
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.terminal-preview .demo-toggle-switch::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.terminal-preview .demo-toggle-switch.active {
|
||||
background: var(--color-accent);
|
||||
}
|
||||
|
||||
.terminal-preview .demo-toggle-switch.active::after {
|
||||
transform: translateX(16px);
|
||||
}
|
||||
|
||||
.terminal-preview .demo-toggle-label {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-ash);
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.terminal-preview .demo-toggle-label.active {
|
||||
color: var(--color-ink);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@keyframes blink { 50% { opacity: 0; } }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { renderCommandDemo } from "../demo-renderer.js";
|
||||
import { setupCommandDemoToggles } from "../demo-toggles.js";
|
||||
import { commandProcessSteps, commandCategories, commandRelationships } from "../data.js";
|
||||
|
||||
export function initGlassTerminal() {
|
||||
// Initial setup if needed
|
||||
@@ -8,11 +9,38 @@ export function initGlassTerminal() {
|
||||
export function renderTerminalLayout(commands) {
|
||||
const container = document.querySelector('.commands-gallery');
|
||||
if (!container) return;
|
||||
|
||||
|
||||
// Group commands by category
|
||||
const categoryOrder = ['diagnostic', 'quality', 'intensity', 'adaptation', 'enhancement', 'system'];
|
||||
const categoryLabels = {
|
||||
'diagnostic': 'Diagnose',
|
||||
'quality': 'Quality',
|
||||
'intensity': 'Intensity',
|
||||
'adaptation': 'Adaptation',
|
||||
'enhancement': 'Enhancement',
|
||||
'system': 'System'
|
||||
};
|
||||
|
||||
const grouped = {};
|
||||
commands.forEach(cmd => {
|
||||
const cat = commandCategories[cmd.id] || 'other';
|
||||
if (!grouped[cat]) grouped[cat] = [];
|
||||
grouped[cat].push(cmd);
|
||||
});
|
||||
|
||||
// Build manual with category headers
|
||||
let manualHTML = '';
|
||||
categoryOrder.forEach(cat => {
|
||||
if (grouped[cat] && grouped[cat].length > 0) {
|
||||
manualHTML += `<div class="command-category-header">${categoryLabels[cat] || cat}</div>`;
|
||||
manualHTML += grouped[cat].map(cmd => renderManualEntry(cmd)).join('');
|
||||
}
|
||||
});
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="commands-container">
|
||||
<div class="command-manual">
|
||||
${commands.map(cmd => renderManualEntry(cmd)).join('')}
|
||||
${manualHTML}
|
||||
</div>
|
||||
<div class="glass-terminal-wrapper">
|
||||
<div class="glass-terminal">
|
||||
@@ -35,7 +63,7 @@ export function renderTerminalLayout(commands) {
|
||||
`;
|
||||
|
||||
setupScrollSpy(commands);
|
||||
|
||||
|
||||
// Select first command initially
|
||||
if (commands.length > 0) {
|
||||
updateTerminal(commands[0], document.getElementById('terminal-content'), commands);
|
||||
@@ -45,10 +73,24 @@ export function renderTerminalLayout(commands) {
|
||||
}
|
||||
|
||||
function renderManualEntry(cmd) {
|
||||
const relationship = commandRelationships[cmd.id];
|
||||
let relationshipHTML = '';
|
||||
|
||||
if (relationship) {
|
||||
if (relationship.pairs) {
|
||||
relationshipHTML = `<div class="manual-cmd-rel"><span class="rel-icon">↔</span> pairs with <code>/${relationship.pairs}</code></div>`;
|
||||
} else if (relationship.leadsTo && relationship.leadsTo.length > 0) {
|
||||
relationshipHTML = `<div class="manual-cmd-rel"><span class="rel-icon">→</span> leads to ${relationship.leadsTo.map(c => `<code>/${c}</code>`).join(', ')}</div>`;
|
||||
} else if (relationship.combinesWith && relationship.combinesWith.length > 0) {
|
||||
relationshipHTML = `<div class="manual-cmd-rel"><span class="rel-icon">+</span> combines with ${relationship.combinesWith.map(c => `<code>/${c}</code>`).join(', ')}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="manual-entry" data-id="${cmd.id}" id="cmd-${cmd.id}">
|
||||
<h3 class="manual-cmd-name">/${cmd.id}</h3>
|
||||
<p class="manual-cmd-desc">${cmd.description}</p>
|
||||
${relationshipHTML}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -56,15 +98,15 @@ function renderManualEntry(cmd) {
|
||||
function setupScrollSpy(commands) {
|
||||
const entries = document.querySelectorAll('.manual-entry');
|
||||
const terminalContent = document.getElementById('terminal-content');
|
||||
|
||||
// Intersection Observer for Scroll Spy
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
|
||||
// Intersection Observer for Scroll Spy - trigger around vertical center
|
||||
const observer = new IntersectionObserver((observerEntries) => {
|
||||
observerEntries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
// Update active state
|
||||
document.querySelectorAll('.manual-entry').forEach(e => e.classList.remove('active'));
|
||||
entry.target.classList.add('active');
|
||||
|
||||
|
||||
// Update terminal
|
||||
const cmdId = entry.target.dataset.id;
|
||||
const cmd = commands.find(c => c.id === cmdId);
|
||||
@@ -74,15 +116,26 @@ function setupScrollSpy(commands) {
|
||||
}
|
||||
});
|
||||
}, {
|
||||
threshold: 0.5,
|
||||
rootMargin: "-20% 0px -60% 0px"
|
||||
threshold: 0.1,
|
||||
rootMargin: "-35% 0px -55% 0px" // Trigger zone biased toward upper-middle of viewport
|
||||
});
|
||||
|
||||
entries.forEach(e => observer.observe(e));
|
||||
|
||||
// Click interaction
|
||||
|
||||
// Click interaction - immediate selection + smooth scroll
|
||||
entries.forEach(e => {
|
||||
e.addEventListener('click', () => {
|
||||
// Immediately update state
|
||||
document.querySelectorAll('.manual-entry').forEach(el => el.classList.remove('active'));
|
||||
e.classList.add('active');
|
||||
|
||||
const cmdId = e.dataset.id;
|
||||
const cmd = commands.find(c => c.id === cmdId);
|
||||
if (cmd) {
|
||||
updateTerminal(cmd, terminalContent, commands);
|
||||
}
|
||||
|
||||
// Then scroll into view
|
||||
e.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
});
|
||||
});
|
||||
@@ -90,30 +143,19 @@ function setupScrollSpy(commands) {
|
||||
|
||||
function updateTerminal(cmd, container, allCommands) {
|
||||
if (!cmd || !container) return;
|
||||
|
||||
// Content update
|
||||
const content = `
|
||||
<div class="terminal-line">
|
||||
<span class="terminal-prompt">➜</span>
|
||||
<span>vibe run ${cmd.id}</span>
|
||||
</div>
|
||||
<div class="terminal-output">
|
||||
> Analyzing design context...<br>
|
||||
> Applying ${cmd.id} transformation...<br>
|
||||
> Done.
|
||||
</div>
|
||||
<div class="terminal-preview">
|
||||
${renderCommandDemo(cmd.id)}
|
||||
</div>
|
||||
<div class="terminal-line" style="margin-top: auto;">
|
||||
<span class="terminal-prompt">➜</span>
|
||||
<span class="terminal-cursor"></span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
container.innerHTML = content;
|
||||
|
||||
|
||||
// Get process steps for this command (or use generic fallback)
|
||||
const steps = commandProcessSteps[cmd.id] || ['Analyze', 'Transform', 'Verify'];
|
||||
const stepsOutput = steps.map((step, i) =>
|
||||
`<span class="terminal-step">${i + 1}. ${step}...</span>`
|
||||
).join('<br>');
|
||||
|
||||
// Content update - no extra indentation to avoid whitespace
|
||||
container.innerHTML = `<div class="terminal-line"><span class="terminal-prompt">➜</span><span class="terminal-cmd">/${cmd.id}</span></div>
|
||||
<div class="terminal-output">${stepsOutput}<br><span class="terminal-done">✓ Complete</span></div>
|
||||
<div class="terminal-preview command-demo-area">${renderCommandDemo(cmd.id)}</div>
|
||||
<div class="terminal-line terminal-cursor-line"><span class="terminal-prompt">➜</span><span class="terminal-cursor"></span></div>`;
|
||||
|
||||
// Re-bind toggles
|
||||
// We pass a no-op for the callback because scrolling handles selection now
|
||||
setupCommandDemoToggles(allCommands, () => {});
|
||||
setupCommandDemoToggles(allCommands, () => {});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
// Adapt command demo - shows desktop-only design becoming responsive
|
||||
export default {
|
||||
id: 'adapt',
|
||||
caption: 'Fixed layout → Responsive across devices',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 280px; display: flex; gap: 12px; align-items: flex-end;">
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 48px; height: 80px; background: #f5f5f5; border: 2px solid #ddd; border-radius: 6px; padding: 4px; box-sizing: border-box;">
|
||||
<div style="height: 100%; display: flex; flex-direction: column; gap: 2px; overflow: hidden;">
|
||||
<div style="height: 16px; background: #ccc; border-radius: 2px;"></div>
|
||||
<div style="height: 8px; background: #e0e0e0; border-radius: 1px; width: 80%;"></div>
|
||||
<div style="height: 8px; background: #e0e0e0; border-radius: 1px; font-size: 6px; color: #999; overflow: hidden;">Text too small...</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size: 9px; color: #999; margin-top: 4px;">Mobile</div>
|
||||
<div style="font-size: 8px; color: #cc0000;">Broken ✗</div>
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 100px; height: 70px; background: #f5f5f5; border: 2px solid #ddd; border-radius: 4px; padding: 6px; box-sizing: border-box;">
|
||||
<div style="display: flex; gap: 4px; height: 100%;">
|
||||
<div style="width: 25%; background: #ccc; border-radius: 2px;"></div>
|
||||
<div style="flex: 1; display: flex; flex-direction: column; gap: 2px;">
|
||||
<div style="height: 12px; background: #e0e0e0; border-radius: 2px;"></div>
|
||||
<div style="flex: 1; background: #eee; border-radius: 2px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size: 9px; color: #999; margin-top: 4px;">Desktop</div>
|
||||
<div style="font-size: 8px; color: #22c55e;">Works ✓</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 280px; display: flex; gap: 12px; align-items: flex-end;">
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 48px; height: 80px; background: var(--color-paper); border: 2px solid var(--color-mist); border-radius: 6px; padding: 4px; box-sizing: border-box;">
|
||||
<div style="height: 100%; display: flex; flex-direction: column; gap: 3px;">
|
||||
<div style="height: 12px; background: var(--color-ink); border-radius: 2px;"></div>
|
||||
<div style="flex: 1; background: var(--color-mist); border-radius: 2px;"></div>
|
||||
<div style="height: 14px; background: var(--color-accent); border-radius: 2px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size: 9px; color: var(--color-ash); margin-top: 4px;">Mobile</div>
|
||||
<div style="font-size: 8px; color: #22c55e;">Stacked ✓</div>
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 72px; height: 56px; background: var(--color-paper); border: 2px solid var(--color-mist); border-radius: 4px; padding: 4px; box-sizing: border-box;">
|
||||
<div style="height: 100%; display: flex; flex-direction: column; gap: 2px;">
|
||||
<div style="height: 10px; background: var(--color-ink); border-radius: 2px;"></div>
|
||||
<div style="flex: 1; display: flex; gap: 2px;">
|
||||
<div style="flex: 1; background: var(--color-mist); border-radius: 2px;"></div>
|
||||
<div style="flex: 1; background: var(--color-mist); border-radius: 2px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size: 9px; color: var(--color-ash); margin-top: 4px;">Tablet</div>
|
||||
<div style="font-size: 8px; color: #22c55e;">2-col ✓</div>
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 100px; height: 64px; background: var(--color-paper); border: 2px solid var(--color-mist); border-radius: 4px; padding: 4px; box-sizing: border-box;">
|
||||
<div style="display: flex; gap: 3px; height: 100%;">
|
||||
<div style="width: 20%; background: var(--color-charcoal); border-radius: 2px;"></div>
|
||||
<div style="flex: 1; display: flex; flex-direction: column; gap: 2px;">
|
||||
<div style="height: 10px; background: var(--color-ink); border-radius: 2px;"></div>
|
||||
<div style="flex: 1; display: flex; gap: 2px;">
|
||||
<div style="flex: 1; background: var(--color-mist); border-radius: 2px;"></div>
|
||||
<div style="flex: 1; background: var(--color-mist); border-radius: 2px;"></div>
|
||||
<div style="flex: 1; background: var(--color-mist); border-radius: 2px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size: 9px; color: var(--color-ash); margin-top: 4px;">Desktop</div>
|
||||
<div style="font-size: 8px; color: #22c55e;">Sidebar ✓</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -1,36 +1,41 @@
|
||||
// Animate command demo - shows static page becoming choreographed
|
||||
// Animate command demo - shows static elements becoming choreographed
|
||||
export default {
|
||||
id: 'animate',
|
||||
caption: 'Static page → Choreographed page load',
|
||||
|
||||
// This demo uses CSS animations triggered by data-state attribute
|
||||
// The before/after states are the same HTML, animation is CSS-driven
|
||||
caption: 'Static layout → Choreographed entrance',
|
||||
|
||||
before: `
|
||||
<div class="motion-demo-page" style="opacity: 1;">
|
||||
<div class="motion-demo-page-hero" style="opacity: 1; transform: none;">Hero</div>
|
||||
<div class="motion-demo-page-content">
|
||||
<div class="motion-demo-page-heading" style="opacity: 1; transform: none;"></div>
|
||||
<div class="motion-demo-page-text" style="opacity: 1; transform: none;"></div>
|
||||
<div class="motion-demo-page-text" style="opacity: 1; transform: none;"></div>
|
||||
<div class="motion-demo-page-text" style="opacity: 1; transform: none;"></div>
|
||||
<div style="width: 100%; max-width: 220px; display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="height: 32px; background: #e0e0e0; border-radius: 4px;"></div>
|
||||
<div style="height: 12px; background: #e0e0e0; border-radius: 2px; width: 60%;"></div>
|
||||
<div style="display: flex; gap: 8px; margin-top: 8px;">
|
||||
<div style="flex: 1; height: 64px; background: #e0e0e0; border-radius: 4px;"></div>
|
||||
<div style="flex: 1; height: 64px; background: #e0e0e0; border-radius: 4px;"></div>
|
||||
</div>
|
||||
<div style="height: 10px; background: #e0e0e0; border-radius: 2px; width: 80%; margin-top: 8px;"></div>
|
||||
<div style="height: 10px; background: #e0e0e0; border-radius: 2px; width: 65%;"></div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: null, // Uses CSS animation, no HTML change needed
|
||||
|
||||
// Custom toggle handler for animation re-triggering
|
||||
onToggle: (viewport, isAfter) => {
|
||||
viewport.dataset.state = isAfter ? 'after' : 'before';
|
||||
if (isAfter) {
|
||||
// Re-trigger animation by cloning the element
|
||||
const page = viewport.querySelector('.motion-demo-page');
|
||||
if (page) {
|
||||
const clone = page.cloneNode(true);
|
||||
page.parentNode.replaceChild(clone, page);
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 220px; display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="height: 32px; background: var(--color-ink); border-radius: 4px; animation: animDemoFade 0.5s ease-out both;"></div>
|
||||
<div style="height: 12px; background: var(--color-ash); border-radius: 2px; width: 60%; animation: animDemoFade 0.5s ease-out 0.1s both;"></div>
|
||||
<div style="display: flex; gap: 8px; margin-top: 8px;">
|
||||
<div style="flex: 1; height: 64px; background: var(--color-mist); border-radius: 4px; animation: animDemoSlide 0.4s ease-out 0.2s both;"></div>
|
||||
<div style="flex: 1; height: 64px; background: var(--color-mist); border-radius: 4px; animation: animDemoSlide 0.4s ease-out 0.3s both;"></div>
|
||||
</div>
|
||||
<div style="height: 10px; background: var(--color-mist); border-radius: 2px; width: 80%; margin-top: 8px; animation: animDemoFade 0.4s ease-out 0.4s both;"></div>
|
||||
<div style="height: 10px; background: var(--color-mist); border-radius: 2px; width: 65%; animation: animDemoFade 0.4s ease-out 0.5s both;"></div>
|
||||
</div>
|
||||
<style>
|
||||
@keyframes animDemoFade {
|
||||
from { opacity: 0; transform: translateY(8px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
viewportClass: 'demo-viewport-dark'
|
||||
@keyframes animDemoSlide {
|
||||
from { opacity: 0; transform: translateY(16px) scale(0.95); }
|
||||
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||
}
|
||||
</style>
|
||||
`
|
||||
};
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Audit command demo - shows scattered issues being identified and flagged
|
||||
export default {
|
||||
id: 'audit',
|
||||
caption: 'Hidden issues → Identified problems with recommendations',
|
||||
|
||||
before: `
|
||||
<div style="display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 260px;">
|
||||
<div style="padding: 12px; background: #f8f8f8; border-radius: 4px;">
|
||||
<div style="font-size: 12px; color: #aaa;">Welcome message</div>
|
||||
<button style="margin-top: 8px; padding: 4px 8px; font-size: 11px; background: #ddd; border: none; border-radius: 2px; color: #888;">click here</button>
|
||||
</div>
|
||||
<div style="padding: 16px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 8px;">
|
||||
<div style="font-size: 15px; color: rgba(255,255,255,0.7);">Featured Item</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 4px;">
|
||||
<button style="width: 20px; height: 20px; font-size: 10px; background: #eee; border: none;">←</button>
|
||||
<button style="width: 20px; height: 20px; font-size: 10px; background: #eee; border: none;">→</button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 280px;">
|
||||
<div style="padding: 12px; background: #fff8f8; border: 1px solid #ffcccc; border-radius: 4px; position: relative;">
|
||||
<div style="position: absolute; top: -8px; right: 8px; background: #ff4444; color: white; font-size: 9px; padding: 2px 6px; border-radius: 8px; font-weight: 600;">CONTRAST</div>
|
||||
<div style="font-size: 12px; color: #aaa;">Welcome message</div>
|
||||
<button style="margin-top: 8px; padding: 4px 8px; font-size: 11px; background: #ddd; border: none; border-radius: 2px; color: #888;">click here</button>
|
||||
</div>
|
||||
<div style="padding: 16px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 8px; border: 2px solid #ff9800; position: relative;">
|
||||
<div style="position: absolute; top: -8px; right: 8px; background: #ff9800; color: white; font-size: 9px; padding: 2px 6px; border-radius: 8px; font-weight: 600;">READABILITY</div>
|
||||
<div style="font-size: 15px; color: rgba(255,255,255,0.7);">Featured Item</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 4px; padding: 4px; background: #fff3e0; border: 1px solid #ffcc80; border-radius: 4px; position: relative;">
|
||||
<div style="position: absolute; top: -8px; right: 8px; background: #ff9800; color: white; font-size: 9px; padding: 2px 6px; border-radius: 8px; font-weight: 600;">TOUCH TARGET</div>
|
||||
<button style="width: 20px; height: 20px; font-size: 10px; background: #eee; border: none;">←</button>
|
||||
<button style="width: 20px; height: 20px; font-size: 10px; background: #eee; border: none;">→</button>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
// Clarify command demo - shows confusing UX copy becoming clear
|
||||
export default {
|
||||
id: 'clarify',
|
||||
caption: 'Confusing copy → Clear, actionable language',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 260px; display: flex; flex-direction: column; gap: 12px;">
|
||||
<div style="padding: 12px; background: #f5f5f5; border-radius: 6px;">
|
||||
<div style="font-size: 13px; font-weight: 600; margin-bottom: 4px;">Processing Status</div>
|
||||
<div style="font-size: 12px; color: #666;">Your request is being processed. Please wait while we complete the operation. This may take some time depending on various factors.</div>
|
||||
</div>
|
||||
<div style="padding: 12px; background: #fff8e1; border-radius: 6px;">
|
||||
<div style="font-size: 13px; font-weight: 600; margin-bottom: 4px;">⚠️ Warning</div>
|
||||
<div style="font-size: 12px; color: #666;">Proceeding with this action may result in irreversible consequences to your data and settings configuration.</div>
|
||||
</div>
|
||||
<button style="padding: 10px; background: #333; color: white; border: none; border-radius: 4px; font-size: 13px;">Submit Request</button>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 260px; display: flex; flex-direction: column; gap: 12px;">
|
||||
<div style="padding: 12px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 6px;">
|
||||
<div style="font-size: 0.8125rem; font-weight: 600; color: var(--color-ink); margin-bottom: 4px;">Saving changes...</div>
|
||||
<div style="font-size: 0.75rem; color: var(--color-ash);">About 10 seconds remaining</div>
|
||||
<div style="margin-top: 8px; height: 4px; background: var(--color-mist); border-radius: 2px; overflow: hidden;">
|
||||
<div style="width: 60%; height: 100%; background: var(--color-accent);"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 12px; background: #fef3c7; border: 1px solid #fcd34d; border-radius: 6px;">
|
||||
<div style="font-size: 0.8125rem; font-weight: 600; color: #92400e; margin-bottom: 4px;">Delete this project?</div>
|
||||
<div style="font-size: 0.75rem; color: #a16207; line-height: 1.5;">This will permanently delete 23 files. You can't undo this.</div>
|
||||
</div>
|
||||
<button style="padding: 10px; background: var(--color-ink); color: var(--color-paper); border: none; border-radius: 6px; font-size: 0.8125rem; font-weight: 500;">Save and Continue →</button>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
// Colorize command demo - shows monochrome becoming strategically colored
|
||||
export default {
|
||||
id: 'colorize',
|
||||
caption: 'Monochrome UI → Strategic, harmonious color',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 240px; padding: 16px; background: #f5f5f5; border: 1px solid #e0e0e0; border-radius: 6px;">
|
||||
<div style="font-size: 11px; color: #999; margin-bottom: 12px;">TASK OVERVIEW</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; padding: 8px; background: white; border: 1px solid #e0e0e0; border-radius: 4px;">
|
||||
<div style="width: 8px; height: 8px; background: #ccc; border-radius: 2px;"></div>
|
||||
<span style="font-size: 12px; color: #666;">Design review</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px; padding: 8px; background: white; border: 1px solid #e0e0e0; border-radius: 4px;">
|
||||
<div style="width: 8px; height: 8px; background: #ccc; border-radius: 2px;"></div>
|
||||
<span style="font-size: 12px; color: #666;">Update copy</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px; padding: 8px; background: white; border: 1px solid #e0e0e0; border-radius: 4px;">
|
||||
<div style="width: 8px; height: 8px; background: #ccc; border-radius: 2px;"></div>
|
||||
<span style="font-size: 12px; color: #666;">Final QA</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid #e0e0e0;">
|
||||
<div style="font-size: 11px; color: #999;">Progress: 1 of 3</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 240px; padding: 16px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 8px;">
|
||||
<div style="font-size: 0.6875rem; letter-spacing: 0.08em; color: var(--color-ash); margin-bottom: 12px;">TASK OVERVIEW</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 10px; background: color-mix(in oklch, var(--color-accent) 8%, var(--color-paper)); border: 1px solid color-mix(in oklch, var(--color-accent) 20%, var(--color-paper)); border-radius: 6px;">
|
||||
<div style="width: 18px; height: 18px; background: var(--color-accent); border-radius: 4px; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px;">✓</div>
|
||||
<span style="font-size: 0.8125rem; color: var(--color-ink); text-decoration: line-through; opacity: 0.6;">Design review</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 10px; background: var(--color-paper); border: 2px solid var(--color-accent); border-radius: 6px;">
|
||||
<div style="width: 18px; height: 18px; border: 2px solid var(--color-accent); border-radius: 4px; background: white;"></div>
|
||||
<span style="font-size: 0.8125rem; color: var(--color-ink); font-weight: 500;">Update copy</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 10px; padding: 10px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 6px;">
|
||||
<div style="width: 18px; height: 18px; border: 1px solid var(--color-mist); border-radius: 4px; background: white;"></div>
|
||||
<span style="font-size: 0.8125rem; color: var(--color-ash);">Final QA</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--color-mist);">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<div style="flex: 1; height: 4px; background: var(--color-mist); border-radius: 2px; overflow: hidden;">
|
||||
<div style="width: 33%; height: 100%; background: var(--color-accent);"></div>
|
||||
</div>
|
||||
<span style="font-size: 0.6875rem; color: var(--color-accent); font-weight: 500;">1/3</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
// Delight command demo - shows functional UI gaining moments of joy
|
||||
export default {
|
||||
id: 'delight',
|
||||
caption: 'Functional feedback → Moment of joy',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 200px; display: flex; flex-direction: column; align-items: center; gap: 16px;">
|
||||
<div style="text-align: center;">
|
||||
<div style="font-size: 13px; color: #666; margin-bottom: 8px;">Milestone reached</div>
|
||||
<div style="font-size: 24px; font-weight: bold; color: #333;">100</div>
|
||||
<div style="font-size: 12px; color: #999;">tasks completed</div>
|
||||
</div>
|
||||
<button style="padding: 8px 16px; background: #e0e0e0; border: none; border-radius: 4px; font-size: 12px; color: #666;">Dismiss</button>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 240px; display: flex; flex-direction: column; align-items: center; gap: 16px; position: relative;">
|
||||
<div style="position: absolute; top: -20px; left: 50%; transform: translateX(-50%); display: flex; gap: 4px;">
|
||||
<span style="animation: confettiFall 1s ease-out 0.0s both; font-size: 16px;">🎊</span>
|
||||
<span style="animation: confettiFall 1s ease-out 0.1s both; font-size: 14px;">✨</span>
|
||||
<span style="animation: confettiFall 1s ease-out 0.2s both; font-size: 16px;">🎉</span>
|
||||
<span style="animation: confettiFall 1s ease-out 0.15s both; font-size: 14px;">✨</span>
|
||||
<span style="animation: confettiFall 1s ease-out 0.25s both; font-size: 16px;">🎊</span>
|
||||
</div>
|
||||
<div style="text-align: center; animation: celebratePop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) both;">
|
||||
<div style="font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--color-accent); margin-bottom: 8px; font-weight: 600;">Milestone unlocked!</div>
|
||||
<div style="font-family: var(--font-display); font-size: 3.5rem; font-weight: 300; font-style: italic; color: var(--color-ink); line-height: 1;">100</div>
|
||||
<div style="font-size: 0.875rem; color: var(--color-ash); margin-top: 4px;">tasks completed</div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 6px; padding: 8px 16px; background: color-mix(in oklch, var(--color-accent) 10%, var(--color-paper)); border-radius: 20px; animation: badgeSlide 0.5s ease-out 0.3s both;">
|
||||
<span style="font-size: 14px;">🏆</span>
|
||||
<span style="font-size: 0.75rem; font-weight: 600; color: var(--color-accent);">Centurion Badge Earned</span>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
@keyframes confettiFall {
|
||||
0% { opacity: 0; transform: translateY(-20px) rotate(0deg); }
|
||||
50% { opacity: 1; }
|
||||
100% { opacity: 0; transform: translateY(40px) rotate(180deg); }
|
||||
}
|
||||
@keyframes celebratePop {
|
||||
0% { opacity: 0; transform: scale(0.5); }
|
||||
70% { transform: scale(1.05); }
|
||||
100% { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
@keyframes badgeSlide {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
</style>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
// Extract command demo - shows patterns being identified and documented
|
||||
export default {
|
||||
id: 'extract',
|
||||
caption: 'Scattered styles → Documented design tokens',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 280px; display: flex; flex-direction: column; gap: 6px; font-family: monospace; font-size: 11px;">
|
||||
<div style="padding: 8px; background: #1e1e1e; color: #d4d4d4; border-radius: 4px; overflow: hidden;">
|
||||
<span style="color: #9cdcfe;">padding</span><span style="color: #d4d4d4;">: </span><span style="color: #ce9178;">12px 16px</span><span style="color: #d4d4d4;">;</span>
|
||||
</div>
|
||||
<div style="padding: 8px; background: #1e1e1e; color: #d4d4d4; border-radius: 4px; overflow: hidden;">
|
||||
<span style="color: #9cdcfe;">padding</span><span style="color: #d4d4d4;">: </span><span style="color: #ce9178;">18px 24px</span><span style="color: #d4d4d4;">;</span>
|
||||
</div>
|
||||
<div style="padding: 8px; background: #1e1e1e; color: #d4d4d4; border-radius: 4px; overflow: hidden;">
|
||||
<span style="color: #9cdcfe;">color</span><span style="color: #d4d4d4;">: </span><span style="color: #ce9178;">#3b82f6</span><span style="color: #d4d4d4;">;</span>
|
||||
</div>
|
||||
<div style="padding: 8px; background: #1e1e1e; color: #d4d4d4; border-radius: 4px; overflow: hidden;">
|
||||
<span style="color: #9cdcfe;">color</span><span style="color: #d4d4d4;">: </span><span style="color: #ce9178;">#3a80f5</span><span style="color: #d4d4d4;">;</span>
|
||||
</div>
|
||||
<div style="padding: 8px; background: #1e1e1e; color: #d4d4d4; border-radius: 4px; overflow: hidden;">
|
||||
<span style="color: #9cdcfe;">font-size</span><span style="color: #d4d4d4;">: </span><span style="color: #ce9178;">14px</span><span style="color: #d4d4d4;">;</span>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 280px; display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--color-ash); margin-bottom: 4px;">Design Tokens</div>
|
||||
<div style="padding: 10px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 6px;">
|
||||
<div style="font-size: 10px; color: var(--color-ash); margin-bottom: 6px;">SPACING</div>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 24px; height: 8px; background: var(--color-accent); border-radius: 2px; margin-bottom: 4px;"></div>
|
||||
<span style="font-family: monospace; font-size: 9px; color: var(--color-charcoal);">sm</span>
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 32px; height: 8px; background: var(--color-accent); border-radius: 2px; margin-bottom: 4px;"></div>
|
||||
<span style="font-family: monospace; font-size: 9px; color: var(--color-charcoal);">md</span>
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 48px; height: 8px; background: var(--color-accent); border-radius: 2px; margin-bottom: 4px;"></div>
|
||||
<span style="font-family: monospace; font-size: 9px; color: var(--color-charcoal);">lg</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 10px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 6px;">
|
||||
<div style="font-size: 10px; color: var(--color-ash); margin-bottom: 6px;">COLORS</div>
|
||||
<div style="display: flex; gap: 6px;">
|
||||
<div style="width: 24px; height: 24px; background: var(--color-ink); border-radius: 4px;" title="ink"></div>
|
||||
<div style="width: 24px; height: 24px; background: var(--color-charcoal); border-radius: 4px;" title="charcoal"></div>
|
||||
<div style="width: 24px; height: 24px; background: var(--color-accent); border-radius: 4px;" title="accent"></div>
|
||||
<div style="width: 24px; height: 24px; background: var(--color-mist); border-radius: 4px; border: 1px solid var(--color-ash);" title="mist"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 10px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 6px;">
|
||||
<div style="font-size: 10px; color: var(--color-ash); margin-bottom: 6px;">TYPOGRAPHY</div>
|
||||
<div style="font-family: var(--font-display); font-size: 16px; font-style: italic; color: var(--color-ink);">Display</div>
|
||||
<div style="font-size: 12px; color: var(--color-charcoal);">Body text</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
// Harden command demo - shows error handling and edge cases
|
||||
export default {
|
||||
id: 'harden',
|
||||
caption: 'Fragile UI → Robust error handling',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 260px; display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="padding: 16px; background: #fff0f0; border-radius: 6px; text-align: center;">
|
||||
<div style="font-size: 24px; margin-bottom: 8px;">⚠️</div>
|
||||
<div style="font-size: 14px; color: #cc0000; font-weight: 500;">Error</div>
|
||||
<div style="font-size: 12px; color: #888; margin-top: 4px;">Something went wrong</div>
|
||||
<button style="margin-top: 12px; padding: 6px 12px; background: #ddd; border: none; border-radius: 4px; font-size: 12px; color: #666;">OK</button>
|
||||
</div>
|
||||
<div style="padding: 12px; background: #f5f5f5; border-radius: 6px;">
|
||||
<div style="font-size: 11px; color: #999; margin-bottom: 4px;">Form Input</div>
|
||||
<input type="text" value="invalid@" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px; box-sizing: border-box;">
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 260px; display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="padding: 16px; background: color-mix(in oklch, var(--color-accent) 8%, var(--color-paper)); border: 1px solid color-mix(in oklch, var(--color-accent) 20%, var(--color-paper)); border-radius: 8px;">
|
||||
<div style="display: flex; align-items: flex-start; gap: 12px;">
|
||||
<div style="width: 32px; height: 32px; background: var(--color-accent); border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0;">
|
||||
<span style="color: white; font-size: 16px;">!</span>
|
||||
</div>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-size: 0.875rem; font-weight: 600; color: var(--color-ink); margin-bottom: 4px;">Connection failed</div>
|
||||
<div style="font-size: 0.8125rem; color: var(--color-charcoal); line-height: 1.4;">Unable to reach the server. Check your internet connection and try again.</div>
|
||||
<button style="margin-top: 12px; padding: 8px 16px; background: var(--color-accent); color: white; border: none; border-radius: 6px; font-size: 0.8125rem; font-weight: 500; cursor: pointer;">Retry Connection</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 12px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 6px;">
|
||||
<div style="font-size: 11px; color: var(--color-ash); margin-bottom: 4px;">Email Address</div>
|
||||
<input type="text" value="invalid@" style="width: 100%; padding: 8px; border: 2px solid #ef4444; border-radius: 4px; font-size: 13px; box-sizing: border-box; background: #fef2f2;">
|
||||
<div style="font-size: 11px; color: #ef4444; margin-top: 4px;">Please enter a complete email address</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -3,11 +3,35 @@
|
||||
import animate from "./animate.js";
|
||||
import bolder from "./bolder.js";
|
||||
import normalize from "./normalize.js";
|
||||
import audit from "./audit.js";
|
||||
import polish from "./polish.js";
|
||||
import optimize from "./optimize.js";
|
||||
import harden from "./harden.js";
|
||||
import clarify from "./clarify.js";
|
||||
import quieter from "./quieter.js";
|
||||
import simplify from "./simplify.js";
|
||||
import colorize from "./colorize.js";
|
||||
import delight from "./delight.js";
|
||||
import extract from "./extract.js";
|
||||
import adapt from "./adapt.js";
|
||||
import onboard from "./onboard.js";
|
||||
|
||||
export const commandDemos = {
|
||||
normalize,
|
||||
bolder,
|
||||
animate,
|
||||
audit,
|
||||
polish,
|
||||
optimize,
|
||||
harden,
|
||||
clarify,
|
||||
quieter,
|
||||
simplify,
|
||||
colorize,
|
||||
delight,
|
||||
extract,
|
||||
adapt,
|
||||
onboard,
|
||||
};
|
||||
|
||||
export function getCommandDemo(commandId) {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Onboard command demo - shows empty state becoming helpful onboarding
|
||||
export default {
|
||||
id: 'onboard',
|
||||
caption: 'Empty state → Guided onboarding experience',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 260px; padding: 24px; background: #f5f5f5; border: 1px solid #ddd; border-radius: 6px; text-align: center;">
|
||||
<div style="font-size: 32px; opacity: 0.3; margin-bottom: 8px;">📁</div>
|
||||
<div style="font-size: 14px; color: #999;">No items found</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 280px; padding: 24px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 12px; text-align: center;">
|
||||
<div style="width: 64px; height: 64px; margin: 0 auto 16px; background: color-mix(in oklch, var(--color-accent) 15%, var(--color-paper)); border-radius: 16px; display: flex; align-items: center; justify-content: center;">
|
||||
<span style="font-size: 28px;">✨</span>
|
||||
</div>
|
||||
<div style="font-family: var(--font-display); font-size: 1.25rem; font-weight: 400; color: var(--color-ink); margin-bottom: 8px;">Create your first project</div>
|
||||
<div style="font-size: 0.8125rem; color: var(--color-ash); line-height: 1.5; margin-bottom: 20px;">Projects help you organize your work. Start with a template or blank canvas.</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
<button style="padding: 12px; background: var(--color-ink); color: var(--color-paper); border: none; border-radius: 8px; font-size: 0.875rem; font-weight: 500; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px;">
|
||||
<span>+</span> New Project
|
||||
</button>
|
||||
<button style="padding: 10px; background: transparent; color: var(--color-charcoal); border: 1px solid var(--color-mist); border-radius: 8px; font-size: 0.8125rem; cursor: pointer;">Browse Templates</button>
|
||||
</div>
|
||||
<div style="margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--color-mist);">
|
||||
<div style="font-size: 0.6875rem; color: var(--color-ash);">Need help? <span style="color: var(--color-accent); cursor: pointer;">Watch a quick tutorial →</span></div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
// Optimize command demo - shows performance improvements
|
||||
export default {
|
||||
id: 'optimize',
|
||||
caption: 'Heavy, slow UI → Lightweight, performant',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 260px; display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="padding: 12px; background: #f5f5f5; border-radius: 6px;">
|
||||
<div style="font-size: 11px; color: #999; margin-bottom: 4px;">BUNDLE SIZE</div>
|
||||
<div style="height: 8px; background: #e0e0e0; border-radius: 4px; overflow: hidden;">
|
||||
<div style="width: 95%; height: 100%; background: linear-gradient(90deg, #ff6b6b, #ee5a5a);"></div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #ff6b6b; margin-top: 4px; font-weight: 600;">847 KB</div>
|
||||
</div>
|
||||
<div style="padding: 12px; background: #f5f5f5; border-radius: 6px;">
|
||||
<div style="font-size: 11px; color: #999; margin-bottom: 4px;">RENDER TIME</div>
|
||||
<div style="height: 8px; background: #e0e0e0; border-radius: 4px; overflow: hidden;">
|
||||
<div style="width: 80%; height: 100%; background: linear-gradient(90deg, #ffa726, #ff9800);"></div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #ff9800; margin-top: 4px; font-weight: 600;">2.4s</div>
|
||||
</div>
|
||||
<div style="padding: 12px; background: #f5f5f5; border-radius: 6px;">
|
||||
<div style="font-size: 11px; color: #999; margin-bottom: 4px;">LAYOUT SHIFTS</div>
|
||||
<div style="height: 8px; background: #e0e0e0; border-radius: 4px; overflow: hidden;">
|
||||
<div style="width: 60%; height: 100%; background: linear-gradient(90deg, #ffa726, #ff9800);"></div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #ff9800; margin-top: 4px; font-weight: 600;">CLS: 0.18</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 260px; display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="padding: 12px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 6px;">
|
||||
<div style="font-size: 11px; color: var(--color-ash); margin-bottom: 4px;">BUNDLE SIZE</div>
|
||||
<div style="height: 8px; background: var(--color-mist); border-radius: 4px; overflow: hidden;">
|
||||
<div style="width: 25%; height: 100%; background: linear-gradient(90deg, #22c55e, #16a34a);"></div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #22c55e; margin-top: 4px; font-weight: 600;">124 KB <span style="color: var(--color-ash); font-weight: 400;">(-85%)</span></div>
|
||||
</div>
|
||||
<div style="padding: 12px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 6px;">
|
||||
<div style="font-size: 11px; color: var(--color-ash); margin-bottom: 4px;">RENDER TIME</div>
|
||||
<div style="height: 8px; background: var(--color-mist); border-radius: 4px; overflow: hidden;">
|
||||
<div style="width: 15%; height: 100%; background: linear-gradient(90deg, #22c55e, #16a34a);"></div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #22c55e; margin-top: 4px; font-weight: 600;">0.3s <span style="color: var(--color-ash); font-weight: 400;">(-88%)</span></div>
|
||||
</div>
|
||||
<div style="padding: 12px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 6px;">
|
||||
<div style="font-size: 11px; color: var(--color-ash); margin-bottom: 4px;">LAYOUT SHIFTS</div>
|
||||
<div style="height: 8px; background: var(--color-mist); border-radius: 4px; overflow: hidden;">
|
||||
<div style="width: 5%; height: 100%; background: linear-gradient(90deg, #22c55e, #16a34a);"></div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #22c55e; margin-top: 4px; font-weight: 600;">CLS: 0.02 <span style="color: var(--color-ash); font-weight: 400;">(excellent)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
// Polish command demo - shows rough UI becoming refined
|
||||
export default {
|
||||
id: 'polish',
|
||||
caption: 'Rough edges → Refined, pixel-perfect details',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 240px; padding: 16px; background: #f5f5f5; border: 1px solid #ddd; border-radius: 4px;">
|
||||
<div style="font-size: 16px; font-weight: bold; margin-bottom: 8px;">User Profile</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 12px;">
|
||||
<div style="width: 40px; height: 40px; background: #ccc; border-radius: 50%;"></div>
|
||||
<div>
|
||||
<div style="font-size: 14px;">John Doe</div>
|
||||
<div style="font-size: 12px; color: #888;">Developer</div>
|
||||
</div>
|
||||
</div>
|
||||
<button style="width: 100%; padding: 8px; background: #333; color: white; border: none; border-radius: 4px; font-size: 13px;">Edit Profile</button>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 240px; padding: 20px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
|
||||
<div style="font-family: var(--font-display); font-size: 1.125rem; font-weight: 400; margin-bottom: 16px; color: var(--color-ink);">User Profile</div>
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
|
||||
<div style="width: 48px; height: 48px; background: var(--color-ink); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: var(--color-paper); font-weight: 600; font-size: 1.125rem;">JD</div>
|
||||
<div>
|
||||
<div style="font-size: 0.9375rem; font-weight: 500; color: var(--color-ink);">John Doe</div>
|
||||
<div style="font-size: 0.75rem; color: var(--color-ash); letter-spacing: 0.02em;">Developer</div>
|
||||
</div>
|
||||
</div>
|
||||
<button style="width: 100%; padding: 10px; background: var(--color-ink); color: var(--color-paper); border: none; border-radius: 6px; font-size: 0.875rem; font-weight: 500; letter-spacing: 0.01em; cursor: pointer;">Edit Profile</button>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
// Quieter command demo - shows loud design becoming calm
|
||||
export default {
|
||||
id: 'quieter',
|
||||
caption: 'Overwhelming design → Calm, focused interface',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 280px; padding: 16px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 8px; text-align: center;">
|
||||
<div style="font-size: 24px; margin-bottom: 8px;">🎉✨🚀</div>
|
||||
<div style="font-size: 18px; font-weight: 800; color: #ffeb3b; text-transform: uppercase; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); margin-bottom: 8px;">AMAZING DEAL!</div>
|
||||
<div style="font-size: 14px; color: white; margin-bottom: 12px;">Don't miss out on this INCREDIBLE opportunity!!!</div>
|
||||
<div style="display: flex; gap: 8px; justify-content: center;">
|
||||
<button style="padding: 10px 16px; background: #ff4081; color: white; border: none; border-radius: 20px; font-weight: bold; font-size: 14px; text-transform: uppercase; box-shadow: 0 4px 15px rgba(255,64,129,0.4);">BUY NOW!!</button>
|
||||
<button style="padding: 10px 16px; background: #00e676; color: white; border: none; border-radius: 20px; font-weight: bold; font-size: 14px; text-transform: uppercase;">LEARN MORE</button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 280px; padding: 24px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 8px; text-align: center;">
|
||||
<div style="font-family: var(--font-display); font-size: 1.5rem; font-weight: 300; font-style: italic; color: var(--color-ink); margin-bottom: 8px;">Limited Time Offer</div>
|
||||
<div style="font-size: 0.875rem; color: var(--color-ash); margin-bottom: 20px; line-height: 1.5;">Save 20% on annual plans. Offer ends Friday.</div>
|
||||
<div style="display: flex; gap: 12px; justify-content: center;">
|
||||
<button style="padding: 12px 24px; background: var(--color-ink); color: var(--color-paper); border: none; border-radius: 6px; font-size: 0.875rem; font-weight: 500;">View Plans</button>
|
||||
<button style="padding: 12px 24px; background: transparent; color: var(--color-charcoal); border: 1px solid var(--color-mist); border-radius: 6px; font-size: 0.875rem;">Maybe Later</button>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
// Simplify command demo - shows cluttered UI becoming minimal
|
||||
export default {
|
||||
id: 'simplify',
|
||||
caption: 'Cluttered interface → Essential elements only',
|
||||
|
||||
before: `
|
||||
<div style="width: 100%; max-width: 280px; padding: 12px; background: #f5f5f5; border: 1px solid #ddd; border-radius: 6px;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; padding-bottom: 8px; border-bottom: 1px solid #ddd;">
|
||||
<span style="font-size: 12px; color: #666;">Dashboard</span>
|
||||
<div style="display: flex; gap: 4px;">
|
||||
<button style="padding: 2px 6px; font-size: 10px; background: #e0e0e0; border: none; border-radius: 2px;">⚙️</button>
|
||||
<button style="padding: 2px 6px; font-size: 10px; background: #e0e0e0; border: none; border-radius: 2px;">🔔</button>
|
||||
<button style="padding: 2px 6px; font-size: 10px; background: #e0e0e0; border: none; border-radius: 2px;">❓</button>
|
||||
<button style="padding: 2px 6px; font-size: 10px; background: #e0e0e0; border: none; border-radius: 2px;">⋮</button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 6px;">
|
||||
<div style="padding: 8px; background: white; border: 1px solid #e0e0e0; border-radius: 4px; font-size: 10px; color: #666;">Revenue<br><b>$12,345</b></div>
|
||||
<div style="padding: 8px; background: white; border: 1px solid #e0e0e0; border-radius: 4px; font-size: 10px; color: #666;">Users<br><b>1,234</b></div>
|
||||
<div style="padding: 8px; background: white; border: 1px solid #e0e0e0; border-radius: 4px; font-size: 10px; color: #666;">Growth<br><b>+12%</b></div>
|
||||
<div style="padding: 8px; background: white; border: 1px solid #e0e0e0; border-radius: 4px; font-size: 10px; color: #666;">Bounce<br><b>32%</b></div>
|
||||
</div>
|
||||
<div style="margin-top: 8px; padding: 8px; background: #e3f2fd; border-radius: 4px; font-size: 10px; color: #1976d2;">📊 View detailed analytics →</div>
|
||||
<div style="margin-top: 4px; padding: 8px; background: #fff3e0; border-radius: 4px; font-size: 10px; color: #e65100;">🎯 Set up goals →</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
after: `
|
||||
<div style="width: 100%; max-width: 260px; padding: 20px; background: var(--color-paper); border: 1px solid var(--color-mist); border-radius: 8px;">
|
||||
<div style="font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--color-ash); margin-bottom: 16px;">This Month</div>
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div style="font-family: var(--font-display); font-size: 2.5rem; font-weight: 300; color: var(--color-ink); line-height: 1;">$12,345</div>
|
||||
<div style="font-size: 0.8125rem; color: #22c55e; margin-top: 4px;">↑ 12% from last month</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 24px;">
|
||||
<div>
|
||||
<div style="font-size: 1.25rem; font-weight: 500; color: var(--color-ink);">1,234</div>
|
||||
<div style="font-size: 0.6875rem; color: var(--color-ash);">Active users</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 1.25rem; font-weight: 500; color: var(--color-ink);">68%</div>
|
||||
<div style="font-size: 0.6875rem; color: var(--color-ash);">Retention</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
+1
-1
@@ -68,7 +68,7 @@ antipatterns:
|
||||
items:
|
||||
- Don't animate without purpose
|
||||
- Don't use durations over 500ms for UI feedback
|
||||
- Don't animate layout properties (use transform)
|
||||
- Don't animate layout properties (width, height, padding, margin) - they trigger reflows and can cause text wrapping mid-animation; use transform instead
|
||||
- Don't ignore prefers-reduced-motion
|
||||
- Don't use animation to hide slow loading
|
||||
- name: Interaction
|
||||
|
||||
Reference in New Issue
Block a user