Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1843522b45 | ||
|
|
41ddecf5a7 | ||
|
|
b06c37affa |
@@ -750,8 +750,9 @@ function elementById(id) {
|
||||
const overflowOrder = [".operator-layout-picker", ".header-style-pick", "#theme-toggle"];
|
||||
function anchorMenu(button, menu) {
|
||||
const rect = button.getBoundingClientRect();
|
||||
if (menu.parentElement !== document.body) document.body.appendChild(menu);
|
||||
menu.style.position = "fixed";
|
||||
menu.style.zIndex = "200";
|
||||
menu.style.zIndex = "9700";
|
||||
menu.style.top = "0px";
|
||||
menu.style.bottom = "auto";
|
||||
menu.style.right = "auto";
|
||||
@@ -798,7 +799,11 @@ function elementById(id) {
|
||||
if (open) anchorMenu(button, menu);
|
||||
});
|
||||
document.addEventListener("click", (event) => {
|
||||
if (!(event.target instanceof Node) || !wrap.contains(event.target)) closeMenu();
|
||||
if (!(event.target instanceof Node)) {
|
||||
closeMenu();
|
||||
return;
|
||||
}
|
||||
if (!wrap.contains(event.target) && !menu.contains(event.target)) closeMenu();
|
||||
});
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape") closeMenu();
|
||||
@@ -838,7 +843,8 @@ function elementById(id) {
|
||||
more.id = "mobile-more-btn";
|
||||
more.className = "tab mobile-more-btn";
|
||||
more.type = "button";
|
||||
more.innerHTML = '<span class="tab-more-icon" aria-hidden="true">•••</span><span class="tab-label">More</span>';
|
||||
more.innerHTML = '<span class="tab-more-icon" aria-hidden="true">•••</span><span class="tab-label">Tools</span>';
|
||||
more.setAttribute("aria-label", "Tools and settings");
|
||||
more.setAttribute("aria-haspopup", "menu");
|
||||
more.setAttribute("aria-expanded", "false");
|
||||
const menu = document.createElement("div");
|
||||
|
||||
@@ -1051,6 +1051,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
</template>
|
||||
</div>
|
||||
<div id="tab-statistics" class="tab-panel" style="display:none;">
|
||||
<h2 class="section-heading">Statistics</h2>
|
||||
<template id="tmpl-statistics">
|
||||
<div class="stats-controls">
|
||||
<div class="stats-control-group">
|
||||
@@ -1191,6 +1192,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
</section>
|
||||
</div>
|
||||
<div id="tab-settings" class="tab-panel" style="display:none;">
|
||||
<h2 class="section-heading">Settings</h2>
|
||||
<div class="sub-tab-bar">
|
||||
<button class="sub-tab active" data-subtab="settings-scheduler">Scheduler</button>
|
||||
<button class="sub-tab" data-subtab="settings-background-decode">Background Decode</button>
|
||||
@@ -1486,6 +1488,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
</div>
|
||||
</div>
|
||||
<div id="tab-about" class="tab-panel" style="display:none;">
|
||||
<h2 class="section-heading">About</h2>
|
||||
<div id="auth-badge" style="display:none; margin-bottom: 1rem; padding: 0.5rem; background: var(--bg-secondary); border-radius: 0.25rem; color: var(--text-muted); font-size: 0.85rem;">Authenticated as: <strong id="auth-role-badge">--</strong></div>
|
||||
<template id="tmpl-about">
|
||||
<div class="sub-tab-bar">
|
||||
|
||||
@@ -1541,6 +1541,7 @@ small { color: var(--text-muted); }
|
||||
* More always fit, so the strip never has to hide a destination. */
|
||||
@media (max-width: 1180px) and (min-width: 701px) {
|
||||
.tab-bar-nav .tab .tab-label { display: none; }
|
||||
.tab-bar-nav .tab .tab-icon, .tab-bar-nav .tab .tab-more-icon { display: block; }
|
||||
.tab-bar-nav .tab { padding: 0.5rem 0.6rem; }
|
||||
}
|
||||
.tab {
|
||||
@@ -1564,6 +1565,7 @@ small { color: var(--text-muted); }
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tab-label { display: block; }
|
||||
.tab-more-icon { display: none; }
|
||||
.about-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1rem; }
|
||||
.about-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 0.5rem; padding: 0; overflow: hidden; }
|
||||
.about-card-title { display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 0.75rem; font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-heading); border-bottom: 1px solid var(--border); background: color-mix(in srgb, var(--card-bg) 50%, var(--bg)); }
|
||||
@@ -3277,7 +3279,7 @@ body[data-operator-layout="broadcast"] #cw-bar-overlay {
|
||||
color: var(--text);
|
||||
box-shadow: inset 0 1px 0 color-mix(in srgb, #ffffff 8%, transparent);
|
||||
}
|
||||
.tab-icon { display: block; }
|
||||
.tab-icon, .tab-more-icon { display: block; }
|
||||
/* Shorten long tab labels to keep bottom nav compact */
|
||||
.tab[data-tab="bookmarks"] .tab-label { font-size: 0.6rem; }
|
||||
.tab[data-tab="digital-modes"] .tab-label { font-size: 0.6rem; }
|
||||
@@ -5442,3 +5444,14 @@ body[data-operator-layout="broadcast"] #cw-bar-overlay {
|
||||
.top-bar-more-menu.is-open { display: flex; }
|
||||
.top-bar-more-menu > * { width: 100%; }
|
||||
.top-bar-more-menu select { width: 100%; max-width: none; }
|
||||
|
||||
|
||||
/* Page title for destinations reached through the Tools menu. The tab strip
|
||||
* cannot show which of them is active, so each states its own name. */
|
||||
.section-heading {
|
||||
margin: 0 0 var(--space-3);
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
@@ -334,8 +334,14 @@ function elementById<T extends HTMLElement>(id: string): T {
|
||||
// edge.
|
||||
function anchorMenu(button: HTMLElement, menu: HTMLElement) {
|
||||
const rect = button.getBoundingClientRect();
|
||||
// Reparent to the body. Fixed positioning escapes clipping but not
|
||||
// stacking: the header sets `z-index: 2`, which makes it a stacking
|
||||
// context, so any z-index the menu carries is confined below every panel
|
||||
// that paints above level 2 — the spectrum overlays reach 9600. Only
|
||||
// leaving that subtree lets the menu sit above the page.
|
||||
if (menu.parentElement !== document.body) document.body.appendChild(menu);
|
||||
menu.style.position = "fixed";
|
||||
menu.style.zIndex = "200";
|
||||
menu.style.zIndex = "9700";
|
||||
menu.style.top = "0px";
|
||||
menu.style.bottom = "auto";
|
||||
// The stylesheet pins these menus to the right of their anchor; leaving
|
||||
@@ -386,7 +392,8 @@ function elementById<T extends HTMLElement>(id: string): T {
|
||||
if (open) anchorMenu(button, menu);
|
||||
});
|
||||
document.addEventListener("click", (event) => {
|
||||
if (!(event.target instanceof Node) || !wrap.contains(event.target)) closeMenu();
|
||||
if (!(event.target instanceof Node)) { closeMenu(); return; }
|
||||
if (!wrap.contains(event.target) && !menu.contains(event.target)) closeMenu();
|
||||
});
|
||||
document.addEventListener("keydown", (event) => { if (event.key === "Escape") closeMenu(); });
|
||||
|
||||
@@ -441,7 +448,8 @@ function elementById<T extends HTMLElement>(id: string): T {
|
||||
more.id = "mobile-more-btn";
|
||||
more.className = "tab mobile-more-btn";
|
||||
more.type = "button";
|
||||
more.innerHTML = '<span class="tab-more-icon" aria-hidden="true">•••</span><span class="tab-label">More</span>';
|
||||
more.innerHTML = '<span class="tab-more-icon" aria-hidden="true">•••</span><span class="tab-label">Tools</span>';
|
||||
more.setAttribute("aria-label", "Tools and settings");
|
||||
more.setAttribute("aria-haspopup", "menu");
|
||||
more.setAttribute("aria-expanded", "false");
|
||||
const menu = document.createElement("div");
|
||||
|
||||
Reference in New Issue
Block a user