Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion ui-concepts/console-euclid-live/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,21 @@ function renderTabs() {
tab.className = "strip-tab" + (seg.id === engine.state.selectedId ? " active" : "");
tab.type = "button";
tab.innerHTML = `
<div class="tab-id"><span>CH ${seg.id + 1}</span><span>${seg.length}px</span></div>
<div class="tab-id">
<span>CH ${seg.id + 1} · ${seg.length}px</span>
<span class="tab-cog" role="button" tabindex="-1" aria-label="Channel settings">
<svg viewBox="0 0 24 24" fill="currentColor"><circle cx="5" cy="12" r="1.8"/><circle cx="12" cy="12" r="1.8"/><circle cx="19" cy="12" r="1.8"/></svg>
</span>
</div>
<div class="tab-name">${eff ? eff.name : seg.effect}</div>
<div class="tab-bar"><i style="background:${segSwatchCss(seg)}"></i></div>
`;
tab.addEventListener("click", () => engine.selectSegment(seg.id));
tab.querySelector(".tab-cog").addEventListener("click", (e) => {
e.stopPropagation();
engine.selectSegment(seg.id);
openSegPopover(seg.id);
});
wrap.appendChild(tab);
});

Expand Down Expand Up @@ -329,10 +339,31 @@ function deleteActiveChannel() {
const seg = engine.selectedSegment();
if (!seg) return;
engine.deleteSegment(seg.id);
closeSegPopover();
showToast(`CH ${seg.id + 1} removed`);
}
$("#deleteChannelBtn").addEventListener("click", deleteActiveChannel);

/* Per-channel settings popover — opened by the ⋯ on a tab. Holds the channel's
range editor + remove (moved out of the Controls card). The inputs keep their
ids, so the range/delete wiring below is unchanged; the popover always targets
the selected channel (the ⋯ selects it before opening). */
function openSegPopover(segId) {
const seg = engine.segmentById(segId);
if (!seg) return;
const eff = engine.effectById(seg.effect);
$("#segPopTitle").textContent = "CH " + (seg.id + 1);
$("#segPopSub").textContent = eff ? eff.name : String(seg.effect);
$("#segPopBackdrop").classList.add("show");
$("#segPopover").classList.add("show");
}
function closeSegPopover() {
$("#segPopBackdrop").classList.remove("show");
$("#segPopover").classList.remove("show");
}
$("#segPopBackdrop").addEventListener("click", closeSegPopover);
document.addEventListener("keydown", (e) => { if (e.key === "Escape") closeSegPopover(); });

// Editable segment boundaries. Commit on change (blur / Enter); the engine
// clamps to the strip and PUTs {start}/{length}. Enter blurs to commit.
function commitRange(field) {
Expand Down
51 changes: 29 additions & 22 deletions ui-concepts/console-euclid-live/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -172,24 +172,6 @@
</span>
</div>

<div class="field-block">
<span class="field-label">Segment Range</span>
<div class="range-edit">
<label class="range-field">
<span class="jack-label">Start</span>
<input type="number" class="jack-input" id="rangeStartInput" min="0" step="1" />
</label>
<label class="range-field">
<span class="jack-label">Length</span>
<input type="number" class="jack-input" id="rangeLengthInput" min="1" step="1" />
</label>
<div class="range-field range-end">
<span class="jack-label">End</span>
<b id="rangeEnd">—</b>
</div>
</div>
</div>

<div class="field-block">
<span class="field-label">Effect</span>
<div class="effect-grid" id="effectGrid"></div>
Expand All @@ -199,10 +181,6 @@
<div id="dynamicControls"></div>
</div>

<div class="field-block strip-actions">
<button class="rack-add" id="deleteChannelBtn" type="button">Remove Channel</button>
</div>

</div>

<!-- AI Prompt (moved to bottom — scroll to reach) -->
Expand Down Expand Up @@ -517,6 +495,35 @@
</div>
</div>

<!-- Per-channel settings popover (opened by the ⋯ on a tab) -->
<div class="popover-backdrop" id="segPopBackdrop"></div>
<div class="seg-popover" id="segPopover" role="dialog" aria-label="Channel settings">
<div class="seg-pop-head">
<span class="seg-pop-title" id="segPopTitle">CH 1</span>
<span class="seg-pop-sub" id="segPopSub">—</span>
</div>
<div class="field-block">
<span class="field-label">Segment Range</span>
<div class="range-edit">
<label class="range-field">
<span class="jack-label">Start</span>
<input type="number" class="jack-input" id="rangeStartInput" min="0" step="1" />
</label>
<label class="range-field">
<span class="jack-label">Length</span>
<input type="number" class="jack-input" id="rangeLengthInput" min="1" step="1" />
</label>
<div class="range-field range-end">
<span class="jack-label">End</span>
<b id="rangeEnd">—</b>
</div>
</div>
</div>
<div class="seg-pop-actions">
<button class="rack-add seg-remove" id="deleteChannelBtn" type="button">Remove Channel</button>
</div>
</div>

<div class="toast" id="toast"></div>

<script src="../_engine/engine.js"></script>
Expand Down
78 changes: 78 additions & 0 deletions ui-concepts/console-euclid-live/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,21 @@ input, button, textarea{ font-family: inherit; color: inherit; }
box-shadow: none;
}

/* Keep the CONSOLE/SETTINGS toggle on-screen on narrow viewports: the rail is
otherwise all flex-shrink:0 and overflows off the right edge. Shed the
decorative model number + divider first, then tighten spacing on the
smallest screens so the wordmark + toggle always fit. */
@media (max-width: 620px){
.brand-model{ display: none; }
.brand-plate{ padding-right: 0; border-right: none; }
}
@media (max-width: 440px){
.top-rail{ padding: 12px 12px; gap: 8px; }
.brand{ gap: 9px; }
.brand-plate .mark{ font-size: 18px; letter-spacing: 0.2em; }
.nav-toggle button{ padding: 7px 11px; }
}

/* ==========================================================================
Views
========================================================================== */
Expand Down Expand Up @@ -1633,6 +1648,69 @@ input, button, textarea{ font-family: inherit; color: inherit; }
transform: scale(1) translateY(0);
pointer-events: auto;
}

/* ── Per-channel ⋯ button + settings popover ───────────────────────────── */
.tab-cog{
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px; height: 16px;
margin: -3px -4px -3px 6px;
border-radius: 3px;
color: var(--c-text-faint);
cursor: pointer;
transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.tab-cog:hover{ color: var(--c-text); background: var(--c-line-soft); }
.tab-cog svg{ width: 15px; height: 15px; }
.strip-tab.active .tab-cog{ color: var(--c-text-dim); }

.seg-popover{
position: fixed;
z-index: 51;
left: 50%; top: 50%;
transform: translate(-50%, -48%) scale(0.98);
width: min(320px, calc(100vw - 32px));
background: var(--c-chassis);
border: var(--hair) solid var(--c-text);
border-radius: var(--radius-panel);
padding: 16px;
opacity: 0;
pointer-events: none;
transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
}
.seg-popover.show{
opacity: 1;
transform: translate(-50%, -50%) scale(1);
pointer-events: auto;
}
.seg-pop-head{
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 14px;
}
.seg-pop-title{
font-family: var(--font-display);
font-style: italic;
font-size: 16px;
color: var(--c-text);
}
.seg-pop-sub{
font-family: var(--font-mono);
font-size: 10px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--c-text-faint);
}
.seg-pop-actions{
margin-top: 16px;
padding-top: 14px;
border-top: var(--hair) solid var(--c-line-soft);
}
.seg-pop-actions .seg-remove{ width: 100%; }
.seg-remove:hover{ color: var(--c-red); border-color: var(--c-red); }
.cp-preview{
height: 38px;
border-radius: var(--radius-ctl);
Expand Down
Loading