fix: horizontal toolbar layout + fix component button placement
Redesign toolbar sections to use horizontal button rows instead of vertical stacking. Fix component placement by attaching click handlers directly to dynamically created buttons and passing correct gate object shape to getComponentWidth/Height. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -78,7 +78,21 @@ body {
|
|||||||
.gate-btn.output-btn { border-color: #ff8833; }
|
.gate-btn.output-btn { border-color: #ff8833; }
|
||||||
.gate-btn.output-btn:hover { border-color: #ffaa55; }
|
.gate-btn.output-btn:hover { border-color: #ffaa55; }
|
||||||
|
|
||||||
.separator { width: 1px; height: 24px; background: #2a2a3a; margin: 0 6px; }
|
.separator { width: 1px; height: 32px; background: #2a2a3a; margin: 0 6px; }
|
||||||
|
|
||||||
|
.create-component-btn {
|
||||||
|
padding: 4px 10px;
|
||||||
|
background: #1a1a2e;
|
||||||
|
border: 1px solid #9900ff;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: #9900ff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.15s;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.create-component-btn:hover { background: #252540; border-color: #cc66ff; color: #cc66ff; }
|
||||||
.toolbar-right { margin-left: auto; display: flex; gap: 6px; align-items: center; }
|
.toolbar-right { margin-left: auto; display: flex; gap: 6px; align-items: center; }
|
||||||
|
|
||||||
.action-btn {
|
.action-btn {
|
||||||
@@ -102,49 +116,54 @@ body {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 1px;
|
gap: 2px;
|
||||||
height: 56px;
|
padding: 4px 0;
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-label {
|
.section-label {
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
color: #666;
|
color: #555;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
padding: 1px 6px;
|
padding: 0 2px;
|
||||||
height: 10px;
|
line-height: 1;
|
||||||
line-height: 10px;
|
}
|
||||||
|
|
||||||
|
.section-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 3px;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-section .gate-btn {
|
.toolbar-section .gate-btn {
|
||||||
padding: 3px 8px;
|
padding: 4px 10px;
|
||||||
font-size: 10px;
|
font-size: 11px;
|
||||||
height: 20px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-section #saved-components {
|
.toolbar-section #saved-components {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 2px;
|
gap: 3px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-section .component-btn {
|
.toolbar-section .component-btn {
|
||||||
padding: 4px 8px;
|
padding: 4px 10px;
|
||||||
font-size: 10px;
|
font-size: 11px;
|
||||||
background: #1a1a2e;
|
background: #1a1a2e;
|
||||||
border: 1px solid #2a2a3a;
|
border: 1px solid #2a2a3a;
|
||||||
border-radius: 4px;
|
border-radius: 6px;
|
||||||
color: #9900ff;
|
color: #9900ff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
transition: all 0.15s;
|
transition: all 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-section .component-btn:hover {
|
.toolbar-section .component-btn:hover {
|
||||||
border-color: #9900ff;
|
border-color: #9900ff;
|
||||||
color: #cc66ff;
|
color: #cc66ff;
|
||||||
|
background: #252540;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================== Canvas ==================== */
|
/* ==================== Canvas ==================== */
|
||||||
|
|||||||
28
index.html
28
index.html
@@ -13,9 +13,11 @@
|
|||||||
<!-- I/O Section -->
|
<!-- I/O Section -->
|
||||||
<div class="toolbar-section">
|
<div class="toolbar-section">
|
||||||
<div class="section-label">I/O</div>
|
<div class="section-label">I/O</div>
|
||||||
<button class="gate-btn input-btn" data-gate="INPUT">INPUT</button>
|
<div class="section-buttons">
|
||||||
<button class="gate-btn clock-btn" data-gate="CLOCK">CLOCK</button>
|
<button class="gate-btn input-btn" data-gate="INPUT">INPUT</button>
|
||||||
<button class="gate-btn output-btn" data-gate="OUTPUT">OUTPUT</button>
|
<button class="gate-btn clock-btn" data-gate="CLOCK">CLOCK</button>
|
||||||
|
<button class="gate-btn output-btn" data-gate="OUTPUT">OUTPUT</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
@@ -23,12 +25,14 @@
|
|||||||
<!-- Gates Section -->
|
<!-- Gates Section -->
|
||||||
<div class="toolbar-section">
|
<div class="toolbar-section">
|
||||||
<div class="section-label">Gates</div>
|
<div class="section-label">Gates</div>
|
||||||
<button class="gate-btn" data-gate="AND">AND</button>
|
<div class="section-buttons">
|
||||||
<button class="gate-btn" data-gate="OR">OR</button>
|
<button class="gate-btn" data-gate="AND">AND</button>
|
||||||
<button class="gate-btn" data-gate="NOT">NOT</button>
|
<button class="gate-btn" data-gate="OR">OR</button>
|
||||||
<button class="gate-btn" data-gate="NAND">NAND</button>
|
<button class="gate-btn" data-gate="NOT">NOT</button>
|
||||||
<button class="gate-btn" data-gate="NOR">NOR</button>
|
<button class="gate-btn" data-gate="NAND">NAND</button>
|
||||||
<button class="gate-btn" data-gate="XOR">XOR</button>
|
<button class="gate-btn" data-gate="NOR">NOR</button>
|
||||||
|
<button class="gate-btn" data-gate="XOR">XOR</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
@@ -36,8 +40,10 @@
|
|||||||
<!-- Components Section -->
|
<!-- Components Section -->
|
||||||
<div class="toolbar-section" id="components-section">
|
<div class="toolbar-section" id="components-section">
|
||||||
<div class="section-label">Components</div>
|
<div class="section-label">Components</div>
|
||||||
<button class="gate-btn create-component-btn" id="create-component-btn" title="Create custom component">✚ Create</button>
|
<div class="section-buttons">
|
||||||
<div id="saved-components"></div>
|
<button class="create-component-btn" id="create-component-btn" title="Create custom component">✚ Create</button>
|
||||||
|
<div id="saved-components"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
|
|||||||
@@ -283,6 +283,10 @@ export function updateComponentButtons() {
|
|||||||
btn.dataset.componentId = comp.id;
|
btn.dataset.componentId = comp.id;
|
||||||
btn.textContent = comp.name;
|
btn.textContent = comp.name;
|
||||||
btn.title = `${comp.inputCount} input(s), ${comp.outputCount} output(s)`;
|
btn.title = `${comp.inputCount} input(s), ${comp.outputCount} output(s)`;
|
||||||
|
btn.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
state.placingGate = `COMPONENT:${comp.id}`;
|
||||||
|
});
|
||||||
container.appendChild(btn);
|
container.appendChild(btn);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
15
js/events.js
15
js/events.js
@@ -71,8 +71,9 @@ export function initEvents() {
|
|||||||
const componentId = state.placingGate.substring(10);
|
const componentId = state.placingGate.substring(10);
|
||||||
const component = state.customComponents?.[componentId];
|
const component = state.customComponents?.[componentId];
|
||||||
if (component) {
|
if (component) {
|
||||||
w = getComponentWidth({ component });
|
const fakeGate = { type: state.placingGate, component };
|
||||||
h = getComponentHeight({ component });
|
w = getComponentWidth(fakeGate);
|
||||||
|
h = getComponentHeight(fakeGate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,14 +349,6 @@ export function initEvents() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Event delegation for saved component buttons
|
// Update component buttons initially
|
||||||
document.addEventListener('click', e => {
|
|
||||||
if (e.target.classList.contains('component-btn')) {
|
|
||||||
const componentId = e.target.dataset.componentId;
|
|
||||||
state.placingGate = `COMPONENT:${componentId}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update component buttons initially and when customComponents changes
|
|
||||||
updateComponentButtons();
|
updateComponentButtons();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user