[feat](trx-frontend-http): make the SQL label the squelch switch
CI / lint (push) Successful in 2m17s
CI / test (push) Successful in 8m13s
CI / frontend (push) Failing after 30s
CI / reuse (push) Successful in 3s

Clicking SQL turns the squelch on and off.  The label and the button
beside it said the same thing twice — one naming the control, the other
reading "On" or "Off" — where the name itself is the obvious target, and
the dot already carries the state: grey when off, green while the gate
passes, amber while it holds.

The pressed state is on the label, so the switch reads the same to a
screen reader as it looks.

Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
sjg
2026-08-03 23:41:52 +02:00
parent 0fc2115973
commit 2c56d82a81
5 changed files with 33 additions and 12 deletions
@@ -6358,15 +6358,15 @@ function renderSdrSquelch() {
} }
if (sdrSquelchDbEl) sdrSquelchDbEl.disabled = !sdrSquelchSupported; if (sdrSquelchDbEl) sdrSquelchDbEl.disabled = !sdrSquelchSupported;
if (sdrSquelchToggleBtn) { if (sdrSquelchToggleBtn) {
sdrSquelchToggleBtn.textContent = sdrSquelchEnabled ? "On" : "Off";
sdrSquelchToggleBtn.setAttribute("aria-pressed", String(sdrSquelchEnabled)); sdrSquelchToggleBtn.setAttribute("aria-pressed", String(sdrSquelchEnabled));
sdrSquelchToggleBtn.title = sdrSquelchEnabled ? "Turn the squelch off" : "Turn the squelch on";
} }
const state = !sdrSquelchEnabled ? "off" : sdrSquelchIsPassing() ? "open" : "closed"; const state = !sdrSquelchEnabled ? "off" : sdrSquelchIsPassing() ? "open" : "closed";
if (sdrSquelchStateEl) { if (sdrSquelchStateEl) {
sdrSquelchStateEl.dataset.state = state; sdrSquelchStateEl.dataset.state = state;
sdrSquelchStateEl.setAttribute( sdrSquelchStateEl.parentElement?.setAttribute(
"aria-label", "aria-label",
state === "off" ? "Squelch off" : state === "open" ? "Squelch open" : "Squelch closed" state === "off" ? "Squelch off" : state === "open" ? "Squelch on, open" : "Squelch on, closed"
); );
} }
if (squelchLabelEl) squelchLabelEl.textContent = String(sdrSquelchThresholdDb); if (squelchLabelEl) squelchLabelEl.textContent = String(sdrSquelchThresholdDb);
@@ -416,11 +416,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
<label class="vol-label">RX<input type="range" id="rx-vol" min="0" max="100" value="80" class="vol-slider" /><small class="vol-pct" id="rx-vol-pct">80%</small></label> <label class="vol-label">RX<input type="range" id="rx-vol" min="0" max="100" value="80" class="vol-slider" /><small class="vol-pct" id="rx-vol-pct">80%</small></label>
<label class="vol-label">TX<input type="range" id="tx-vol" min="0" max="100" value="80" class="vol-slider" /><small class="vol-pct" id="tx-vol-pct">80%</small></label> <label class="vol-label">TX<input type="range" id="tx-vol" min="0" max="100" value="80" class="vol-slider" /><small class="vol-pct" id="tx-vol-pct">80%</small></label>
<span class="sql-control" id="sdr-squelch-wrap" style="display:none;"> <span class="sql-control" id="sdr-squelch-wrap" style="display:none;">
<span class="sql-title">SQL</span> <button id="sdr-squelch-toggle" type="button" class="sql-toggle" aria-pressed="false" title="Turn the squelch on or off"><span class="sql-state" id="sdr-squelch-state" data-state="off" aria-hidden="true"></span>SQL</button>
<span class="sql-state" id="sdr-squelch-state" data-state="off" role="img" aria-label="Squelch state"></span>
<label class="sql-db"><input type="number" id="sdr-squelch-db" min="-120" max="-30" step="1" value="-95" inputmode="numeric" aria-label="Squelch threshold in dB" /><span class="sql-db-unit">dB</span></label> <label class="sql-db"><input type="number" id="sdr-squelch-db" min="-120" max="-30" step="1" value="-95" inputmode="numeric" aria-label="Squelch threshold in dB" /><span class="sql-db-unit">dB</span></label>
<button id="sdr-squelch-auto" type="button" class="sql-auto-btn" title="Set the threshold just above the noise floor">Auto</button> <button id="sdr-squelch-auto" type="button" class="sql-auto-btn" title="Set the threshold just above the noise floor">Auto</button>
<button id="sdr-squelch-toggle" type="button" class="sql-auto-btn" aria-pressed="false" title="Enable or disable the squelch">Off</button>
</span> </span>
<div id="audio-level"> <div id="audio-level">
<div id="audio-level-fill"></div> <div id="audio-level-fill"></div>
@@ -1856,9 +1856,32 @@ small { color: var(--text-muted); }
font-size: 0.82rem; font-size: 0.82rem;
white-space: nowrap; white-space: nowrap;
} }
.sql-title { /* The name is the switch: one target instead of a label and a button that
said the same thing twice, with the dot carrying the state. */
.sql-toggle {
display: inline-flex;
align-items: center;
gap: 0.3rem;
height: 1.5rem;
min-height: 0;
padding: 0 0.4rem;
border: 1px solid transparent;
border-radius: 4px;
background: transparent;
color: var(--text-muted);
font-size: 0.82rem;
font-weight: 700; font-weight: 700;
letter-spacing: 0.02em; letter-spacing: 0.02em;
cursor: pointer;
}
.sql-toggle:hover {
border-color: color-mix(in srgb, var(--border-light) 60%, transparent);
color: var(--text);
}
.sql-toggle[aria-pressed="true"] {
border-color: color-mix(in srgb, var(--accent-green) 50%, var(--border-light));
background: color-mix(in srgb, var(--accent-green) 10%, transparent);
color: var(--accent-text);
} }
.sql-state { .sql-state {
width: 0.5rem; width: 0.5rem;
@@ -5343,15 +5343,15 @@ function renderSdrSquelch() {
} }
if (sdrSquelchDbEl) sdrSquelchDbEl.disabled = !sdrSquelchSupported; if (sdrSquelchDbEl) sdrSquelchDbEl.disabled = !sdrSquelchSupported;
if (sdrSquelchToggleBtn) { if (sdrSquelchToggleBtn) {
sdrSquelchToggleBtn.textContent = sdrSquelchEnabled ? "On" : "Off";
sdrSquelchToggleBtn.setAttribute("aria-pressed", String(sdrSquelchEnabled)); sdrSquelchToggleBtn.setAttribute("aria-pressed", String(sdrSquelchEnabled));
sdrSquelchToggleBtn.title = sdrSquelchEnabled ? "Turn the squelch off" : "Turn the squelch on";
} }
const state = !sdrSquelchEnabled ? "off" : (sdrSquelchIsPassing() ? "open" : "closed"); const state = !sdrSquelchEnabled ? "off" : (sdrSquelchIsPassing() ? "open" : "closed");
if (sdrSquelchStateEl) { if (sdrSquelchStateEl) {
sdrSquelchStateEl.dataset.state = state; sdrSquelchStateEl.dataset.state = state;
sdrSquelchStateEl.setAttribute( sdrSquelchStateEl.parentElement?.setAttribute(
"aria-label", "aria-label",
state === "off" ? "Squelch off" : (state === "open" ? "Squelch open" : "Squelch closed"), state === "off" ? "Squelch off" : (state === "open" ? "Squelch on, open" : "Squelch on, closed"),
); );
} }
if (squelchLabelEl) squelchLabelEl.textContent = String(sdrSquelchThresholdDb); if (squelchLabelEl) squelchLabelEl.textContent = String(sdrSquelchThresholdDb);
@@ -144,12 +144,12 @@ try {
shown: getComputedStyle(line).display !== "none", shown: getComputedStyle(line).display !== "none",
db: Number(document.getElementById("sdr-squelch-db").value), db: Number(document.getElementById("sdr-squelch-db").value),
label: Number(document.getElementById("spectrum-squelch-label").textContent), label: Number(document.getElementById("spectrum-squelch-label").textContent),
toggle: document.getElementById("sdr-squelch-toggle").textContent, toggle: document.getElementById("sdr-squelch-toggle").getAttribute("aria-pressed"),
top: Math.round(line.getBoundingClientRect().top), top: Math.round(line.getBoundingClientRect().top),
}; };
}); });
assert.equal(squelchOn.shown, true, "the threshold line did not appear with the squelch on"); assert.equal(squelchOn.shown, true, "the threshold line did not appear with the squelch on");
assert.equal(squelchOn.toggle, "On", "the toggle did not follow the squelch state"); assert.equal(squelchOn.toggle, "true", "the SQL switch did not follow the squelch state");
assert.equal(squelchOn.label, squelchOn.db, "the line and the readout disagree on the threshold"); assert.equal(squelchOn.label, squelchOn.db, "the line and the readout disagree on the threshold");
// Dragging the line down lowers the threshold and tells the server. // Dragging the line down lowers the threshold and tells the server.