From 037d17ff3d307b4a8869f009811147542d92595b Mon Sep 17 00:00:00 2001 From: LucasDLTG Date: Wed, 9 Sep 2026 20:56:35 +0200 Subject: [PATCH] feat: graph header on gain panel --- src/assets/icons/Triangle.tsx | 2 +- src/components/Button/Button.css | 43 +++++++--- src/components/ChannelGroup/ChannelGroup.css | 14 +++- .../ChoiceStepper/ChoiceStepper.css | 2 +- .../components/GainSection/GainSection.css | 78 +++++++++++++++++-- .../components/GainSection/GainSection.tsx | 42 +++++----- 6 files changed, 141 insertions(+), 40 deletions(-) diff --git a/src/assets/icons/Triangle.tsx b/src/assets/icons/Triangle.tsx index 78d2201..9784dbb 100644 --- a/src/assets/icons/Triangle.tsx +++ b/src/assets/icons/Triangle.tsx @@ -24,4 +24,4 @@ export function TriangleDownIcon(props: React.SVGProps) { /> ); -} \ No newline at end of file +} diff --git a/src/components/Button/Button.css b/src/components/Button/Button.css index 73110de..11275db 100644 --- a/src/components/Button/Button.css +++ b/src/components/Button/Button.css @@ -2,23 +2,19 @@ display: flex; align-items: center; justify-content: center; - box-sizing: border-box; min-height: var(--card-control-height); - padding: 0 var(--space-4); border: var(--border-width) solid transparent; border-radius: var(--radius-sm); font-family: var(--font-ui); - font-size: var(--font-md); + font-size: 13px; font-weight: var(--font-weight-medium); cursor: pointer; - - font-size: 13px; } .btn:disabled { @@ -26,27 +22,49 @@ cursor: not-allowed; } +/* ------------------------------------------------------------------ */ +/* Variants */ +/* ------------------------------------------------------------------ */ + .btn-primary { background: var(--accent-brand); color: var(--bg-void); } +/* Ghost + Toggle */ .btn-ghost, -.btn-toggle, -.btn-outline { +.btn-toggle { background: transparent; border-color: var(--border-hairline); color: var(--text-muted); } +/* Outline */ +.btn-outline { + background: transparent; + border-color: var(--accent-brand); + color: #fff; +} + +/* ------------------------------------------------------------------ */ +/* Hover */ +/* ------------------------------------------------------------------ */ + .btn-ghost:hover:not(:disabled), -.btn-toggle:hover:not(:disabled), -.btn-outline:hover:not(:disabled) { +.btn-toggle:hover:not(:disabled) { background: var(--bg-raised); color: var(--text-primary); } -/* Active toggle states */ +.btn-outline:hover:not(:disabled) { + border-color: var(--accent-brand); + color: var(--text-muted); +} + +/* ------------------------------------------------------------------ */ +/* Active toggle states */ +/* ------------------------------------------------------------------ */ + .btn-toggle.active-info { background: var(--accent-brand); border-color: var(--accent-brand); @@ -65,7 +83,10 @@ color: var(--bg-void); } -/* Optional: active state hover */ +/* ------------------------------------------------------------------ */ +/* Active toggle hover */ +/* ------------------------------------------------------------------ */ + .btn-toggle.active-info:hover:not(:disabled) { background: var(--accent-brand); border-color: var(--accent-brand); diff --git a/src/components/ChannelGroup/ChannelGroup.css b/src/components/ChannelGroup/ChannelGroup.css index 0737a85..b45afc5 100644 --- a/src/components/ChannelGroup/ChannelGroup.css +++ b/src/components/ChannelGroup/ChannelGroup.css @@ -1,18 +1,21 @@ .channel-group { position: relative; - /* flex: 1 1 0; */ - min-height: 0; + flex: 0 0 auto; + width: fit-content; + min-width: 0; + + min-height: 0; display: flex; border: var(--border-width) solid var(--border-hairline); border-radius: var(--radius-md); - padding: 6cqh var(--space-3) 1cqh; margin-bottom: 1cqh; margin-top: 1cqh; + box-sizing: border-box; - overflow: visible; /* in case something upstream set hidden */ + overflow: visible; } .channel-group__label { @@ -36,6 +39,9 @@ display: flex; flex-direction: row; align-items: stretch; + + width: fit-content; height: 100%; + gap: var(--space-1); } diff --git a/src/components/ChoiceStepper/ChoiceStepper.css b/src/components/ChoiceStepper/ChoiceStepper.css index 877ee5f..c8c1914 100644 --- a/src/components/ChoiceStepper/ChoiceStepper.css +++ b/src/components/ChoiceStepper/ChoiceStepper.css @@ -34,7 +34,7 @@ } .choice-stepper__input:focus { - outline: none; + outline: none; } .choice-stepper__arrows { diff --git a/src/features/dsp408/components/GainSection/GainSection.css b/src/features/dsp408/components/GainSection/GainSection.css index d376885..bee7773 100644 --- a/src/features/dsp408/components/GainSection/GainSection.css +++ b/src/features/dsp408/components/GainSection/GainSection.css @@ -22,8 +22,9 @@ } .gain-panels { + display: grid; + grid-auto-flow: column; height: 100%; - display: flex; gap: var(--space-2); overflow-x: auto; } @@ -106,37 +107,94 @@ .gain-graph-title-row { flex: 0 0 auto; + + display: flex; + flex-direction: column; + align-items: stretch; + + gap: 0.75cqh; + padding: 1cqh 1.5cqh; + + min-width: 0; + overflow: hidden; +} + +/* First row: title left, Show stages right */ +.gain-graph-title-line { display: flex; align-items: center; justify-content: space-between; + + width: 100%; + min-width: 0; gap: 1cqh; - padding: 1cqh 1.5cqh; - flex-wrap: wrap; } -.gain-graph-title-row .gain-graph-title { +.gain-graph-title-line .gain-graph-title { + flex: 1 1 auto; + min-width: 0; + padding: 0; + + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } +/* Compact button on the right */ +.gain-stages-toggle { + flex: 0 0 auto; + + width: auto !important; + min-width: max-content; + + padding: 0.4cqh 1cqh; + font-size: 1.8cqh; + line-height: 1.2; + + white-space: nowrap; +} + +/* Channel Selector */ .magnitude-selector { + width: 100%; + min-width: 0; + display: flex; - flex-wrap: wrap; + align-items: center; + flex-wrap: nowrap; + gap: 0.5cqh; + + overflow: hidden; } .magnitude-selector__chip { + flex: 0 1 auto; + min-width: 0; + display: flex; align-items: center; + gap: 0.6cqh; + font-family: var(--font-ui); font-size: 1.8cqh; + padding: 0.4cqh 1cqh; + background: var(--bg-void); color: var(--text-muted); + border: var(--border-width) solid var(--border-hairline); border-radius: var(--radius-sm); + cursor: pointer; opacity: 0.5; + + white-space: nowrap; + overflow: hidden; } .magnitude-selector__chip.active { @@ -148,7 +206,17 @@ .magnitude-selector__swatch { width: 1.2cqh; height: 1.2cqh; + border-radius: 50%; background: var(--chip-color); + flex: 0 0 auto; } + +.magnitude-selector__label { + min-width: 0; + + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/src/features/dsp408/components/GainSection/GainSection.tsx b/src/features/dsp408/components/GainSection/GainSection.tsx index fa94180..30683d6 100644 --- a/src/features/dsp408/components/GainSection/GainSection.tsx +++ b/src/features/dsp408/components/GainSection/GainSection.tsx @@ -117,7 +117,7 @@ function buildCurvesForChannels( ): Curve[] { const curves: Curve[] = []; - channels.forEach((channel) => { + [...channels].reverse().forEach((channel) => { if (!selected.has(channel)) return; const { geq, peqCrossover, total } = getCurves(channel); const color = colors[channel]; @@ -292,9 +292,10 @@ function ChannelSelector({ className={`magnitude-selector__chip${isOn ? ' active' : ''}`} style={{ '--chip-color': colors[channel] } as React.CSSProperties} onClick={() => onToggle(channel)} + title={labels[channel]} > - {labels[channel]} + {labels[channel]} ); })} @@ -427,14 +428,16 @@ function GainSection({
-
Input Response
- +
+
Input Response
+ +
-
Output Response
- +
+
Output Response
+ +
+