From 255b1f217e75160d0a60a967170ca81c3264a10c Mon Sep 17 00:00:00 2001 From: LucasDLTG Date: Tue, 28 Jul 2026 18:41:40 +0200 Subject: [PATCH] feat: improve gain section --- src/components/Button/Button.css | 31 ++++++++ .../dsp408/ChannelGroup/ChannelGroup.css | 21 +++-- .../dsp408/GainSection/GainSection.css | 68 +++++++--------- .../dsp408/GainSection/GainSection.tsx | 30 +------ .../dsp408/GateSection/GateSection.tsx | 60 +++++++------- .../dsp408/LinearGraph/LinearGraph.css | 4 - .../dsp408/Slider/VerticalSlider.css | 78 ++++++------------- .../dsp408/Slider/VerticalSlider.tsx | 33 +------- src/pages/DspPage/DspPage.tsx | 8 +- 9 files changed, 129 insertions(+), 204 deletions(-) diff --git a/src/components/Button/Button.css b/src/components/Button/Button.css index c7a59c9..50c0077 100644 --- a/src/components/Button/Button.css +++ b/src/components/Button/Button.css @@ -36,3 +36,34 @@ border-color: var(--border-hairline); color: var(--text-muted); } + +.btn-ghost:hover:not(:disabled), +.btn-toggle:hover:not(:disabled), +.btn-outline:hover:not(:disabled) { + background: var(--bg-raised); + color: var(--text-primary); +} + +/* Active toggle states */ +.btn-toggle.active-danger { + background: var(--accent-down); + border-color: var(--accent-down); + color: var(--bg-void); +} + +.btn-toggle.active-warning { + background: var(--accent-connecting); + border-color: var(--accent-connecting); + color: var(--bg-void); +} + +/* Optional: active state hover */ +.btn-toggle.active-danger:hover:not(:disabled) { + background: var(--accent-down); + border-color: var(--accent-down); +} + +.btn-toggle.active-warning:hover:not(:disabled) { + background: var(--accent-connecting); + border-color: var(--accent-connecting); +} \ No newline at end of file diff --git a/src/components/dsp408/ChannelGroup/ChannelGroup.css b/src/components/dsp408/ChannelGroup/ChannelGroup.css index b3379e6..291fa90 100644 --- a/src/components/dsp408/ChannelGroup/ChannelGroup.css +++ b/src/components/dsp408/ChannelGroup/ChannelGroup.css @@ -1,16 +1,15 @@ .channel-group { + /* container-type: inline-size; */ position: relative; - height: calc(100% - var(--space-1) - var(--space-1)); - flex: 0 0 auto; + flex: 1 1 0; + min-height: 0; display: flex; - align-items: flex-end; - border: 1px solid var(--border-hairline); + border: var(--border-width) solid var(--border-hairline); border-radius: var(--radius-md); - /* enough top padding to fully clear the label's own height, not just its border-overlap */ - padding: calc(1.2vh + var(--space-3)) var(--space-3) 0; + padding: 4cqh var(--space-3) 0; margin-bottom: var(--space-1); margin-top: var(--space-1); box-sizing: border-box; @@ -19,14 +18,14 @@ .channel-group__label { position: absolute; - top: var(--space-2); /* sits inside the padded space, not straddling the border */ + top: 1cqh; left: 50%; - transform: translateX(-50%); /* only horizontal centering now — no vertical overlap */ + transform: translateX(-50%); padding: 0 var(--space-2); font-family: var(--font-ui); - font-size: var(--tab-close-font); + font-size: 2cqh; font-weight: var(--font-weight-semibold); color: var(--text-muted); @@ -39,5 +38,5 @@ flex-direction: row; align-items: stretch; height: 100%; - gap: var(--space-2); -} + gap: var(--space-1); +} \ No newline at end of file diff --git a/src/components/dsp408/GainSection/GainSection.css b/src/components/dsp408/GainSection/GainSection.css index dac591f..e120c55 100644 --- a/src/components/dsp408/GainSection/GainSection.css +++ b/src/components/dsp408/GainSection/GainSection.css @@ -1,38 +1,3 @@ -.gain-section { - position: absolute; - left: 0; - right: 0; - bottom: 0; - - height: var(--dsp-control-heigth); - - display: flex; - align-items: flex-end; - justify-content: center; - - box-sizing: border-box; - padding: 0 var(--space-4); - - background: var(--bg-panel); - - z-index: 20; - - border-top: var(--border-width) solid var(--border-hairline); -} - -.gain-panels { - height: 100%; - display: flex; - gap: var(--space-4); - overflow-x: auto; -} - -.gain-panel-frame { - flex: 0 0 auto; - height: calc(100% - 2 * var(--space-1)); - margin: var(--space-1) 0; -} - .gain-panel-viewport { position: relative; aspect-ratio: 90 / 400; @@ -56,10 +21,11 @@ box-sizing: border-box; gap: var(--space-2); background: var(--bg-void); + padding-bottom: var(--space-2); } .gain-panel__title { - flex: 0 0 auto; /* NEW: never let this shrink */ + flex: 0 0 auto; width: 100%; text-align: center; font-family: var(--font-ui); @@ -70,8 +36,34 @@ border-bottom: var(--border-width) solid var(--border-hairline); } -.channel-group__label { - font-size: calc(var(--tab-close-font) * var(--panel-scale, 1)); +/* Container */ + +.gain-section { + position: absolute; + left: 0; + right: 0; + bottom: 0; + + height: var(--dsp-control-heigth); + + display: flex; + align-items: flex-end; + justify-content: center; + + box-sizing: border-box; + + background: var(--bg-panel); + + z-index: 20; + + border-top: var(--border-width) solid var(--border-hairline); +} + +.gain-panels { + height: 100%; + display: flex; + gap: var(--space-2); + overflow-x: auto; } /* --- graph strip, sits above the gain section --- diff --git a/src/components/dsp408/GainSection/GainSection.tsx b/src/components/dsp408/GainSection/GainSection.tsx index 925b7a2..fa75b60 100644 --- a/src/components/dsp408/GainSection/GainSection.tsx +++ b/src/components/dsp408/GainSection/GainSection.tsx @@ -10,29 +10,6 @@ import './GainSection.css'; const PANEL_DESIGN_WIDTH = 90; const PANEL_DESIGN_HEIGHT = 400; -// function ChannelGroupScaled({ title, children }: { title: string; children: React.ReactNode }) { -// const wrapperRef = useRef(null); -// const [scale, setScale] = useState(1); - -// useEffect(() => { -// const el = wrapperRef.current; -// if (!el) return; -// const observer = new ResizeObserver((entries) => { -// const { height } = entries[0].contentRect; -// if (height === 0) return; -// setScale(height / PANEL_DESIGN_HEIGHT); // height is the only free axis here -// }); -// observer.observe(el); -// return () => observer.disconnect(); -// }, []); - -// return ( -//
-// {children} -//
-// ); -// } - function GainPanel({ dsp, channel, @@ -101,16 +78,17 @@ function GainPanel({ unit=" dB" value={gain} onChange={(value) => setGain(channel, value)} - style={{ width: 70, height: 260, flex: '0 0 auto' }} // pin to design size, disable its own auto-shrink + style={{ width: 70, height: 250, flex: '0 0 auto' }} // pin to design size, disable its own auto-shrink /> - diff --git a/src/components/dsp408/GateSection/GateSection.tsx b/src/components/dsp408/GateSection/GateSection.tsx index cc57a10..47117af 100644 --- a/src/components/dsp408/GateSection/GateSection.tsx +++ b/src/components/dsp408/GateSection/GateSection.tsx @@ -1,35 +1,31 @@ -// import VerticalSlider from '../Slider/VerticalSlider'; -// import { invoke } from '@tauri-apps/api/core'; -// import { InputChannel, Channel, OutputChannel } from '../../../types/dsp408State'; -// import { DSP } from '../../../types/types'; -// import { NotificationType } from '../../../types/types'; +import VerticalSlider from '../Slider/VerticalSlider'; +import { invoke } from '@tauri-apps/api/core'; +import { InputChannel, Channel, OutputChannel } from '../../../types/dsp408State'; +import { DSP } from '../../../types/types'; +import { NotificationType } from '../../../types/types'; -// import ChannelGroup from '../ChannelGroup/ChannelGroup'; -// import './GateSection.css'; +import ChannelGroup from '../ChannelGroup/ChannelGroup'; +import './GateSection.css'; -// function GateSection({ -// dsp, -// notify, -// }: { -// dsp: DSP; -// notify: (message: string, type?: NotificationType, dspName?: string) => void; -// }) { -// console.log(dsp, notify); -// return ( -//
-// { -// return; -// }} -// /> -//
-// ); -// } +function GateSection({ + dsp, +}: { + dsp: DSP; +}) { + return ( +
+ +
+ ); +} -// export default GateSection; +export default GateSection; diff --git a/src/components/dsp408/LinearGraph/LinearGraph.css b/src/components/dsp408/LinearGraph/LinearGraph.css index dac591f..95322ef 100644 --- a/src/components/dsp408/LinearGraph/LinearGraph.css +++ b/src/components/dsp408/LinearGraph/LinearGraph.css @@ -70,10 +70,6 @@ border-bottom: var(--border-width) solid var(--border-hairline); } -.channel-group__label { - font-size: calc(var(--tab-close-font) * var(--panel-scale, 1)); -} - /* --- graph strip, sits above the gain section --- Requires the shared parent (whatever renders ) to be position: relative — it already must be, for .gain-section's absolute diff --git a/src/components/dsp408/Slider/VerticalSlider.css b/src/components/dsp408/Slider/VerticalSlider.css index a67dfbe..86ea497 100644 --- a/src/components/dsp408/Slider/VerticalSlider.css +++ b/src/components/dsp408/Slider/VerticalSlider.css @@ -1,27 +1,29 @@ .gauge-viewport { - position: relative; + container-type: size; + container-name: gauge; + position: relative; flex: 1 1 0; min-height: 0; width: auto; - aspect-ratio: 70 / 260; - overflow: hidden; } .gauge-container { + --s: min(calc(100cqw / 70), calc(100cqh / 240)); + position: absolute; - top: 50%; + bottom: 0; left: 50%; - width: 70px; - height: 240px; + width: calc(70 * var(--s)); + height: calc(240 * var(--s)); display: flex; flex-direction: column; align-items: center; - transform-origin: center center; + transform: translateX(-50%); box-sizing: border-box; } @@ -29,130 +31,100 @@ .gauge-track { position: relative; - width: 70px; - height: 210px; + width: calc(70 * var(--s)); + height: calc(210 * var(--s)); display: flex; - justify-content: center; align-items: center; - margin-bottom: 8px; + margin-bottom: calc(8 * var(--s)); } .slider { position: relative; - width: 24px; + width: calc(24 * var(--s)); height: 100%; cursor: pointer; - touch-action: none; user-select: none; } .track { position: absolute; - left: 50%; top: 0; transform: translateX(-50%); - width: 2px; - + width: calc(2 * var(--s)); height: 100%; background: var(--border-hairline); - border-radius: var(--radius-sm); } .thumb { position: absolute; - left: 50%; - width: 18px; - + width: calc(18 * var(--s)); aspect-ratio: 1; transform: translate(-50%, 50%); border-radius: 50%; - background: var(--bg-panel); - border: var(--border-width-active) solid var(--accent-brand); - box-shadow: var(--shadow-sm); } .ticks { position: absolute; - top: 0; - height: 100%; display: flex; - flex-direction: column; - justify-content: space-between; pointer-events: none; } .ticks span { - width: 10px; - - height: 2px; + width: calc(10 * var(--s)); + height: calc(2 * var(--s)); background: var(--border-hairline); - border-radius: var(--radius-sm); } -.left { - left: 8px; -} - -.right { - right: 8px; -} +.left { left: calc(8 * var(--s)); } +.right { right: calc(8 * var(--s)); } .value { width: 100%; - margin-top: 4px; - - padding-top: 2px; - padding-bottom: 2px; - padding-right: 4px; - padding-left: 4px; + margin-top: calc(4 * var(--s)); + padding: calc(2 * var(--s)) calc(4 * var(--s)); box-sizing: border-box; display: flex; - justify-content: center; align-items: center; - gap: 0.25em; white-space: nowrap; color: var(--accent-brand); - font-size: var(--font-xxs); - font-family: var(--font-mono); font-weight: var(--font-weight-medium); box-shadow: var(--shadow-sm); - border-radius: var(--radius-md); overflow: hidden; @@ -161,15 +133,12 @@ .value input { width: auto; min-width: 0; - height: 1.4em; text-align: center; - background: transparent; border: var(--border-width) solid var(--border-hairline); - border-radius: var(--radius-sm); appearance: none; @@ -178,10 +147,7 @@ .value input, .value-unit { font-size: inherit; - line-height: 1; - font-family: inherit; - color: inherit; -} +} \ No newline at end of file diff --git a/src/components/dsp408/Slider/VerticalSlider.tsx b/src/components/dsp408/Slider/VerticalSlider.tsx index 2ffef46..2766435 100644 --- a/src/components/dsp408/Slider/VerticalSlider.tsx +++ b/src/components/dsp408/Slider/VerticalSlider.tsx @@ -1,10 +1,7 @@ -import { useMemo, useRef, useState, useEffect } from 'react'; +import { useMemo, useRef, useState } from 'react'; import './VerticalSlider.css'; -const DESIGN_WIDTH = 70; -const DESIGN_HEIGHT = 240; - type VerticalSliderProps = { min: number; max: number; @@ -50,32 +47,6 @@ export default function VerticalSlider({ const thumbRef = useRef(null); const keyboardEditing = useRef(false); - const viewportRef = useRef(null); - const [scale, setScale] = useState(1); - - useEffect(() => { - const el = viewportRef.current; - if (!el) return; - - const observer = new ResizeObserver((entries) => { - const entry = entries[0]; - const { width, height } = entry.contentRect; - if (width === 0 || height === 0) return; - setScale(Math.min(width / DESIGN_WIDTH, height / DESIGN_HEIGHT)); - }); - - observer.observe(el); - return () => observer.disconnect(); - }, []); - - useEffect(() => { - if (dragging.current) return; - if (keyboardEditing.current) return; - - setDisplayValue(value); - dragValue.current = value; - }, [value]); - function getStep(value: number) { if (switchStepValue !== undefined && switchStep !== undefined && value >= switchStepValue) { return switchStep; @@ -218,11 +189,9 @@ export default function VerticalSlider({
diff --git a/src/pages/DspPage/DspPage.tsx b/src/pages/DspPage/DspPage.tsx index 27096aa..e48914c 100644 --- a/src/pages/DspPage/DspPage.tsx +++ b/src/pages/DspPage/DspPage.tsx @@ -6,7 +6,7 @@ import ConnectionPanel from '../../components/dsp408/ConnectionSection/Connectio import GainSection from '../../components/dsp408/GainSection/GainSection'; import { DSP408Device } from '../../hooks/useDSP408'; import './DspPage.css'; -// import GateSection from '../../components/dsp408/GateSection/GateSection'; +import GateSection from '../../components/dsp408/GateSection/GateSection'; import LoadingOverlay from '../../components/LoadingOverlay/LoadingOverlay'; import { InputChannel, OutputChannel } from '../../types/dsp408State'; @@ -147,8 +147,6 @@ function DSPPage({ dsp, dsp408 }: { dsp: DSP; dsp408: DSP408Device }) { })), ]; - // const { recallPreset, setCurrentPresetName } = useDSPPresets(dsp, setDsps, notify); - const onAppChange = async (id: string) => { const presetIndex = presets.findIndex((preset) => preset.id === id); if (presetIndex === -1) return; @@ -178,8 +176,8 @@ function DSPPage({ dsp, dsp408 }: { dsp: DSP; dsp408: DSP408Device }) { /> ); - // case 'gate': - // return ; + case 'gate': + return ; default: return null;