[feat](trx-frontend-http): assign distinct colours to bookmark categories
Named categories are sorted alphabetically and assigned colours from an 8-colour palette (blue, green, orange, red, purple, teal, pink, indigo). Uncategorised bookmarks fall back to --accent-yellow (the leading UI colour). Both the canvas dashed lines and the axis span labels (icon, text, border, background) reflect the category colour via CSS custom properties --bm-cat-color / --bm-cat-bg / --bm-cat-border. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -4273,12 +4273,14 @@ function drawSpectrum(data) {
|
|||||||
? _bmListRef.filter((bm) => bm.freq_hz >= range.visLoHz && bm.freq_hz <= range.visHiHz)
|
? _bmListRef.filter((bm) => bm.freq_hz >= range.visLoHz && bm.freq_hz <= range.visHiHz)
|
||||||
: [];
|
: [];
|
||||||
if (visBookmarks.length > 0) {
|
if (visBookmarks.length > 0) {
|
||||||
|
const colorMap = bmCategoryColorMap();
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.strokeStyle = pal.waveformPeak.replace(/[\d.]+\)$/, "0.65)");
|
|
||||||
ctx.lineWidth = 1 * dpr;
|
ctx.lineWidth = 1 * dpr;
|
||||||
ctx.setLineDash([4 * dpr, 3 * dpr]);
|
ctx.setLineDash([4 * dpr, 3 * dpr]);
|
||||||
for (const bm of visBookmarks) {
|
for (const bm of visBookmarks) {
|
||||||
const x = hzToX(bm.freq_hz);
|
const x = hzToX(bm.freq_hz);
|
||||||
|
const col = colorMap[bm.category || ""];
|
||||||
|
ctx.strokeStyle = col ? bmHexToRgba(col, 0.65) : pal.waveformPeak.replace(/[\d.]+\)$/, "0.65)");
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(x, 0);
|
ctx.moveTo(x, 0);
|
||||||
ctx.lineTo(x, H);
|
ctx.lineTo(x, H);
|
||||||
@@ -4293,6 +4295,34 @@ function drawSpectrum(data) {
|
|||||||
drawSignalOverlay();
|
drawSignalOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Distinct colours for named bookmark categories (uncategorised uses --accent-yellow).
|
||||||
|
const BM_PALETTE = [
|
||||||
|
"#4299e1", // blue
|
||||||
|
"#48bb78", // green
|
||||||
|
"#ed8936", // orange
|
||||||
|
"#f56565", // red
|
||||||
|
"#9f7aea", // purple
|
||||||
|
"#38b2ac", // teal
|
||||||
|
"#ed64a6", // pink
|
||||||
|
"#667eea", // indigo
|
||||||
|
];
|
||||||
|
|
||||||
|
function bmHexToRgba(hex, alpha) {
|
||||||
|
const r = parseInt(hex.slice(1, 3), 16);
|
||||||
|
const g = parseInt(hex.slice(3, 5), 16);
|
||||||
|
const b = parseInt(hex.slice(5, 7), 16);
|
||||||
|
return `rgba(${r},${g},${b},${alpha})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a map of category → hex colour. Empty-string key = uncategorised (no entry).
|
||||||
|
function bmCategoryColorMap() {
|
||||||
|
const ref = typeof bmList !== "undefined" ? bmList : [];
|
||||||
|
const cats = [...new Set(ref.map((b) => b.category).filter(Boolean))].sort();
|
||||||
|
const map = {};
|
||||||
|
cats.forEach((cat, i) => { map[cat] = BM_PALETTE[i % BM_PALETTE.length]; });
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
function updateBookmarkAxis(range) {
|
function updateBookmarkAxis(range) {
|
||||||
const axisEl = document.getElementById("spectrum-bookmark-axis");
|
const axisEl = document.getElementById("spectrum-bookmark-axis");
|
||||||
if (!axisEl) return;
|
if (!axisEl) return;
|
||||||
@@ -4316,6 +4346,7 @@ function updateBookmarkAxis(range) {
|
|||||||
if (axisEl.dataset.bmKey !== newKey) {
|
if (axisEl.dataset.bmKey !== newKey) {
|
||||||
axisEl.dataset.bmKey = newKey;
|
axisEl.dataset.bmKey = newKey;
|
||||||
axisEl.innerHTML = "";
|
axisEl.innerHTML = "";
|
||||||
|
const colorMap = bmCategoryColorMap();
|
||||||
const esc = (s) => String(s)
|
const esc = (s) => String(s)
|
||||||
.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||||
for (const bm of visBookmarks) {
|
for (const bm of visBookmarks) {
|
||||||
@@ -4328,6 +4359,13 @@ function updateBookmarkAxis(range) {
|
|||||||
"<svg class='bm-icon-svg' viewBox='0 0 8 12' width='8' height='12' aria-hidden='true'>" +
|
"<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'/>" +
|
"<path d='M0,0 h8 v10 l-4,2 l-4,-2 Z'/>" +
|
||||||
"</svg>\u00a0" + esc(bm.name);
|
"</svg>\u00a0" + esc(bm.name);
|
||||||
|
// Apply category colour; uncategorised falls back to --accent-yellow via CSS.
|
||||||
|
const col = colorMap[bm.category || ""];
|
||||||
|
if (col) {
|
||||||
|
span.style.setProperty("--bm-cat-color", col);
|
||||||
|
span.style.setProperty("--bm-cat-bg", bmHexToRgba(col, 0.15));
|
||||||
|
span.style.setProperty("--bm-cat-border", bmHexToRgba(col, 0.55));
|
||||||
|
}
|
||||||
span.addEventListener("click", () => {
|
span.addEventListener("click", () => {
|
||||||
if (typeof bmApply === "function") bmApply(bm);
|
if (typeof bmApply === "function") bmApply(bm);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1539,9 +1539,9 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 0.66rem;
|
font-size: 0.66rem;
|
||||||
background: var(--card-bg);
|
background: var(--bm-cat-bg, var(--card-bg));
|
||||||
color: var(--accent-yellow);
|
color: var(--bm-cat-color, var(--accent-yellow));
|
||||||
border: 1px solid color-mix(in srgb, var(--accent-yellow) 55%, transparent);
|
border: 1px solid var(--bm-cat-border, color-mix(in srgb, var(--accent-yellow) 55%, transparent));
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
max-width: 130px;
|
max-width: 130px;
|
||||||
@@ -1553,10 +1553,11 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
#spectrum-bookmark-axis span:hover {
|
#spectrum-bookmark-axis span:hover {
|
||||||
background: color-mix(in srgb, var(--accent-yellow) 28%, transparent);
|
background: var(--bm-cat-bg, color-mix(in srgb, var(--accent-yellow) 28%, transparent));
|
||||||
|
filter: brightness(1.15);
|
||||||
}
|
}
|
||||||
.bm-icon-svg path {
|
.bm-icon-svg path {
|
||||||
fill: var(--accent-yellow);
|
fill: var(--bm-cat-color, var(--accent-yellow));
|
||||||
}
|
}
|
||||||
#spectrum-tooltip {
|
#spectrum-tooltip {
|
||||||
display: none;
|
display: none;
|
||||||
|
|||||||
Reference in New Issue
Block a user