[style](trx-frontend): remove bookmark side shading
Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -526,6 +526,24 @@ const CANVAS_PALETTE = {
|
|||||||
waterfallHue: [45, 18], waterfallSat: 86, waterfallLight: [92, 42], waterfallAlpha: [0.34, 0.82],
|
waterfallHue: [45, 18], waterfallSat: 86, waterfallLight: [92, 42], waterfallAlpha: [0.34, 0.82],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
fire: {
|
||||||
|
dark: {
|
||||||
|
bg: "#130706",
|
||||||
|
spectrumLine: "#ff7a1f", spectrumFill: "rgba(255,122,31,0.14)",
|
||||||
|
spectrumGrid: "rgba(255,110,40,0.09)", spectrumLabel: "rgba(255,202,164,0.54)",
|
||||||
|
waveformLine: "rgba(255,134,54,0.94)", waveformPeak: "rgba(255,220,96,0.92)",
|
||||||
|
waveformGrid: "rgba(255,120,36,0.11)", waveformLabel: "rgba(255,214,176,0.66)",
|
||||||
|
waterfallHue: [8, 42], waterfallSat: 96, waterfallLight: [8, 58], waterfallAlpha: [0.26, 0.88],
|
||||||
|
},
|
||||||
|
light: {
|
||||||
|
bg: "#fff2e7",
|
||||||
|
spectrumLine: "#c24500", spectrumFill: "rgba(194,69,0,0.14)",
|
||||||
|
spectrumGrid: "rgba(125,52,0,0.09)", spectrumLabel: "rgba(90,38,0,0.56)",
|
||||||
|
waveformLine: "rgba(176,62,0,0.95)", waveformPeak: "rgba(224,132,0,0.90)",
|
||||||
|
waveformGrid: "rgba(125,52,0,0.10)", waveformLabel: "rgba(90,38,0,0.68)",
|
||||||
|
waterfallHue: [18, 48], waterfallSat: 90, waterfallLight: [92, 42], waterfallAlpha: [0.34, 0.84],
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function currentStyle() {
|
function currentStyle() {
|
||||||
@@ -540,7 +558,7 @@ function canvasPalette() {
|
|||||||
|
|
||||||
function setStyle(style) {
|
function setStyle(style) {
|
||||||
const remapped = style === "nord" ? "arctic" : style === "monokai" ? "lime" : style;
|
const remapped = style === "nord" ? "arctic" : style === "monokai" ? "lime" : style;
|
||||||
const valid = ["original", "arctic", "lime", "contrast", "neon-disco", "golden-rain"];
|
const valid = ["original", "arctic", "lime", "contrast", "neon-disco", "golden-rain", "fire"];
|
||||||
const next = valid.includes(remapped) ? remapped : "original";
|
const next = valid.includes(remapped) ? remapped : "original";
|
||||||
if (next === "original") {
|
if (next === "original") {
|
||||||
document.documentElement.removeAttribute("data-style");
|
document.documentElement.removeAttribute("data-style");
|
||||||
@@ -4910,19 +4928,35 @@ function bmCategoryColorMap() {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBookmarkChip(bm, colorMap) {
|
function createBookmarkChip(bm, colorMap, options = {}) {
|
||||||
const span = document.createElement("span");
|
const span = document.createElement("span");
|
||||||
const freqStr = typeof bmFmtFreq === "function"
|
const freqStr = typeof bmFmtFreq === "function"
|
||||||
? bmFmtFreq(bm.freq_hz) : bm.freq_hz + "\u202fHz";
|
? bmFmtFreq(bm.freq_hz) : bm.freq_hz + "\u202fHz";
|
||||||
const esc = (s) => String(s)
|
const esc = (s) => String(s)
|
||||||
.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||||
span.className = "spectrum-bookmark-chip";
|
span.className = "spectrum-bookmark-chip";
|
||||||
|
if (options.sideStack) {
|
||||||
|
span.classList.add("spectrum-bookmark-chip-side");
|
||||||
|
}
|
||||||
span.title = bm.name + " \u2014 " + freqStr + (bm.comment ? "\n" + bm.comment : "");
|
span.title = bm.name + " \u2014 " + freqStr + (bm.comment ? "\n" + bm.comment : "");
|
||||||
span.dataset.bmId = bm.id;
|
span.dataset.bmId = bm.id;
|
||||||
|
const labelHtml = options.sideStack
|
||||||
|
? (
|
||||||
|
`<span class="spectrum-bookmark-side-head">` +
|
||||||
|
`<svg class='bm-icon-svg' viewBox='0 0 8 12' width='8' height='12' aria-hidden='true'>` +
|
||||||
|
"<path d='M0,0 h8 v10 l-4,2 l-4,-2 Z'/>" +
|
||||||
|
`</svg>` +
|
||||||
|
`<span class="spectrum-bookmark-freq">${esc(freqStr)}</span>` +
|
||||||
|
`</span>` +
|
||||||
|
`<span class="spectrum-bookmark-name">${esc(bm.name)}</span>`
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
"<svg class='bm-icon-svg' viewBox='0 0 8 12' width='8' height='12' aria-hidden='true'>" +
|
||||||
|
"<path d='M0,0 h8 v10 l-4,2 l-4,-2 Z'/>" +
|
||||||
|
"</svg>\u00a0" + esc(bm.name)
|
||||||
|
);
|
||||||
span.innerHTML =
|
span.innerHTML =
|
||||||
"<svg class='bm-icon-svg' viewBox='0 0 8 12' width='8' height='12' aria-hidden='true'>" +
|
labelHtml;
|
||||||
"<path d='M0,0 h8 v10 l-4,2 l-4,-2 Z'/>" +
|
|
||||||
"</svg>\u00a0" + esc(bm.name);
|
|
||||||
const col = colorMap[bm.category || ""];
|
const col = colorMap[bm.category || ""];
|
||||||
span.style.setProperty("--bm-cat-bg", col);
|
span.style.setProperty("--bm-cat-bg", col);
|
||||||
span.style.setProperty("--bm-cat-fg", bmContrastFg(col));
|
span.style.setProperty("--bm-cat-fg", bmContrastFg(col));
|
||||||
@@ -4948,7 +4982,7 @@ function updateSideBookmarkStack(container, bookmarks, colorMap) {
|
|||||||
container.dataset.bmKey = nextKey;
|
container.dataset.bmKey = nextKey;
|
||||||
container.innerHTML = "";
|
container.innerHTML = "";
|
||||||
for (const bm of bookmarks) {
|
for (const bm of bookmarks) {
|
||||||
container.appendChild(createBookmarkChip(bm, colorMap));
|
container.appendChild(createBookmarkChip(bm, colorMap, { sideStack: true }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
container.classList.add("bm-side-visible");
|
container.classList.add("bm-side-visible");
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
<option value="contrast">Contrast</option>
|
<option value="contrast">Contrast</option>
|
||||||
<option value="neon-disco">Neon Disco</option>
|
<option value="neon-disco">Neon Disco</option>
|
||||||
<option value="golden-rain">Donald</option>
|
<option value="golden-rain">Donald</option>
|
||||||
|
<option value="fire">Fire</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button id="theme-toggle" class="header-bar-btn" type="button" aria-label="Toggle dark or light theme">Light</button>
|
<button id="theme-toggle" class="header-bar-btn" type="button" aria-label="Toggle dark or light theme">Light</button>
|
||||||
@@ -273,6 +274,9 @@
|
|||||||
<select id="bm-category-filter" class="status-input" aria-label="Filter by category">
|
<select id="bm-category-filter" class="status-input" aria-label="Filter by category">
|
||||||
<option value="">All categories</option>
|
<option value="">All categories</option>
|
||||||
</select>
|
</select>
|
||||||
|
<select id="bm-mode-filter" class="status-input" aria-label="Filter by mode">
|
||||||
|
<option value="">All modes</option>
|
||||||
|
</select>
|
||||||
<input type="search" id="bm-text-filter" class="status-input" placeholder="Search bookmarks…" aria-label="Search bookmarks" />
|
<input type="search" id="bm-text-filter" class="status-input" placeholder="Search bookmarks…" aria-label="Search bookmarks" />
|
||||||
<button id="bm-add-btn" type="button" class="bm-add-btn" style="display:none;">+ Add Bookmark</button>
|
<button id="bm-add-btn" type="button" class="bm-add-btn" style="display:none;">+ Add Bookmark</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -51,32 +51,51 @@ async function bmFetch(categoryFilter) {
|
|||||||
|
|
||||||
function bmApplyFilters() {
|
function bmApplyFilters() {
|
||||||
const text = (document.getElementById("bm-text-filter")?.value || "").trim().toLowerCase();
|
const text = (document.getElementById("bm-text-filter")?.value || "").trim().toLowerCase();
|
||||||
const filtered = text
|
const modeFilter = (document.getElementById("bm-mode-filter")?.value || "").trim().toUpperCase();
|
||||||
? bmList.filter((bm) =>
|
let filtered = modeFilter
|
||||||
|
? bmList.filter((bm) => String(bm.mode || "").toUpperCase() === modeFilter)
|
||||||
|
: bmList;
|
||||||
|
filtered = text
|
||||||
|
? filtered.filter((bm) =>
|
||||||
(bm.name || "").toLowerCase().includes(text) ||
|
(bm.name || "").toLowerCase().includes(text) ||
|
||||||
(bm.category || "").toLowerCase().includes(text) ||
|
(bm.category || "").toLowerCase().includes(text) ||
|
||||||
(bm.comment || "").toLowerCase().includes(text)
|
(bm.comment || "").toLowerCase().includes(text)
|
||||||
)
|
)
|
||||||
: bmList;
|
: filtered;
|
||||||
bmRender(filtered);
|
bmRender(filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function bmRefreshCategoryFilter(keepValue) {
|
async function bmRefreshCategoryFilter(keepValue) {
|
||||||
const sel = document.getElementById("bm-category-filter");
|
const sel = document.getElementById("bm-category-filter");
|
||||||
if (!sel) return;
|
const modeSel = document.getElementById("bm-mode-filter");
|
||||||
|
if (!sel && !modeSel) return;
|
||||||
try {
|
try {
|
||||||
const resp = await fetch("/bookmarks");
|
const resp = await fetch("/bookmarks");
|
||||||
if (!resp.ok) return;
|
if (!resp.ok) return;
|
||||||
const all = await resp.json();
|
const all = await resp.json();
|
||||||
const cats = [...new Set(all.map((b) => b.category || "").filter(Boolean))].sort();
|
if (sel) {
|
||||||
while (sel.options.length > 1) sel.remove(1);
|
const cats = [...new Set(all.map((b) => b.category || "").filter(Boolean))].sort();
|
||||||
cats.forEach((cat) => {
|
while (sel.options.length > 1) sel.remove(1);
|
||||||
const opt = document.createElement("option");
|
cats.forEach((cat) => {
|
||||||
opt.value = cat;
|
const opt = document.createElement("option");
|
||||||
opt.textContent = cat;
|
opt.value = cat;
|
||||||
sel.add(opt);
|
opt.textContent = cat;
|
||||||
});
|
sel.add(opt);
|
||||||
if (keepValue && cats.includes(keepValue)) sel.value = keepValue;
|
});
|
||||||
|
if (keepValue && cats.includes(keepValue)) sel.value = keepValue;
|
||||||
|
}
|
||||||
|
if (modeSel) {
|
||||||
|
const keepMode = modeSel.value;
|
||||||
|
const modes = [...new Set(all.map((b) => String(b.mode || "").trim().toUpperCase()).filter(Boolean))].sort();
|
||||||
|
while (modeSel.options.length > 1) modeSel.remove(1);
|
||||||
|
modes.forEach((mode) => {
|
||||||
|
const opt = document.createElement("option");
|
||||||
|
opt.value = mode;
|
||||||
|
opt.textContent = mode;
|
||||||
|
modeSel.add(opt);
|
||||||
|
});
|
||||||
|
if (keepMode && modes.includes(keepMode)) modeSel.value = keepMode;
|
||||||
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,6 +320,11 @@ async function bmApply(bm) {
|
|||||||
bmFetch(e.target.value);
|
bmFetch(e.target.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mode filter dropdown (client-side, no re-fetch)
|
||||||
|
document.getElementById("bm-mode-filter").addEventListener("change", () => {
|
||||||
|
bmApplyFilters();
|
||||||
|
});
|
||||||
|
|
||||||
// Text search filter (client-side, no re-fetch)
|
// Text search filter (client-side, no re-fetch)
|
||||||
document.getElementById("bm-text-filter").addEventListener("input", () => {
|
document.getElementById("bm-text-filter").addEventListener("input", () => {
|
||||||
bmApplyFilters();
|
bmApplyFilters();
|
||||||
|
|||||||
@@ -1656,6 +1656,51 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
transform: none;
|
transform: none;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
.spectrum-bookmark-chip-side {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.16rem;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
padding: 0.38rem 0.5rem 0.42rem;
|
||||||
|
border-radius: 0.55rem;
|
||||||
|
white-space: normal;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
.spectrum-bookmark-side-head {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.32rem;
|
||||||
|
min-width: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.spectrum-bookmark-chip-side .bm-icon-svg {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 0.5rem;
|
||||||
|
height: 0.72rem;
|
||||||
|
opacity: 0.95;
|
||||||
|
}
|
||||||
|
.spectrum-bookmark-chip-side .spectrum-bookmark-freq,
|
||||||
|
.spectrum-bookmark-chip-side .spectrum-bookmark-name {
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.spectrum-bookmark-chip-side .spectrum-bookmark-freq {
|
||||||
|
min-width: 0;
|
||||||
|
font-size: 0.54rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
.spectrum-bookmark-chip-side .spectrum-bookmark-name {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.64rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
.bm-icon-svg path {
|
.bm-icon-svg path {
|
||||||
fill: var(--bm-cat-fg, #1a202c);
|
fill: var(--bm-cat-fg, #1a202c);
|
||||||
}
|
}
|
||||||
@@ -2261,3 +2306,61 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
--wavelength-fg: #87663a;
|
--wavelength-fg: #87663a;
|
||||||
--spectrum-bg: #f5ecd9;
|
--spectrum-bg: #f5ecd9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Fire style ───────────────────────────────────────────────────────── */
|
||||||
|
[data-style="fire"] {
|
||||||
|
--bg: #120706;
|
||||||
|
--card-bg: #1b0c0a;
|
||||||
|
--input-bg: #180907;
|
||||||
|
--border: #4c1a12;
|
||||||
|
--border-light: #7a2e1a;
|
||||||
|
--text: #ffe7d2;
|
||||||
|
--text-muted: #c78361;
|
||||||
|
--text-heading: #fff3e7;
|
||||||
|
--btn-bg: #2c110d;
|
||||||
|
--btn-border: #8f3a20;
|
||||||
|
--accent-green: #ff6f1f;
|
||||||
|
--accent-yellow: #ffb347;
|
||||||
|
--accent-red: #ff4a24;
|
||||||
|
--jog-hi: #381510;
|
||||||
|
--jog-lo: #24100c;
|
||||||
|
--jog-shadow: rgba(0,0,0,0.62);
|
||||||
|
--jog-inset: rgba(255,164,76,0.07);
|
||||||
|
--audio-level-bg: #1f0d0a;
|
||||||
|
--audio-level-border: #7a2e1a;
|
||||||
|
--audio-level-fill-start: #ff4a24;
|
||||||
|
--audio-level-fill-end: #ffb347;
|
||||||
|
--filter-bg: #2b120d;
|
||||||
|
--filter-fg: #ffe7d2;
|
||||||
|
--filter-border: #8f3a20;
|
||||||
|
--wavelength-fg: #d38d6a;
|
||||||
|
--spectrum-bg: #140907;
|
||||||
|
}
|
||||||
|
[data-style="fire"][data-theme="light"] {
|
||||||
|
--bg: #fff3ea;
|
||||||
|
--card-bg: #fff7f0;
|
||||||
|
--input-bg: #ffe9da;
|
||||||
|
--border: #efc7b1;
|
||||||
|
--border-light: #d9a487;
|
||||||
|
--text: #42180d;
|
||||||
|
--text-muted: #8a4b31;
|
||||||
|
--text-heading: #2f120a;
|
||||||
|
--btn-bg: #ffe2cf;
|
||||||
|
--btn-border: #cc8563;
|
||||||
|
--accent-green: #d24c12;
|
||||||
|
--accent-yellow: #d88400;
|
||||||
|
--accent-red: #c53114;
|
||||||
|
--jog-hi: #ffe2cf;
|
||||||
|
--jog-lo: #ffd5bc;
|
||||||
|
--jog-shadow: rgba(108,44,15,0.18);
|
||||||
|
--jog-inset: rgba(255,255,255,0.72);
|
||||||
|
--audio-level-bg: #ffe7d7;
|
||||||
|
--audio-level-border: #d9a487;
|
||||||
|
--audio-level-fill-start: #c53114;
|
||||||
|
--audio-level-fill-end: #d88400;
|
||||||
|
--filter-bg: #ffe2cf;
|
||||||
|
--filter-fg: #42180d;
|
||||||
|
--filter-border: #cc8563;
|
||||||
|
--wavelength-fg: #9a5a3a;
|
||||||
|
--spectrum-bg: #fff0e4;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user