Admin: group the fourteen panels into tabs
The page was a fixed 1.5fr/.75fr split — ten tall panels on the left, four short config forms on the right. The right column ran out about a quarter of the way down, so the rest of the page scrolled past an empty gutter, and finding anything meant scrolling through everything. Five tabs now, each using the full width: Team (queue, add sponsor, coaching radar, award capacity, messages), Traffic (conversions, org vs network), Members (submissions, lookup, matrix), My Money (positions income), Settings (AI chat, SendGrid, public page). The panels themselves are untouched — same markup, same ids, same JS. Only their grouping changed. Panes are moved in the HTML rather than by script, so the layout does not depend on JS running; the tab file only toggles which pane is visible and remembers the last one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
// Admin tab bar. Separate file because the site's CSP is script-src 'self'.
|
||||
//
|
||||
// The admin page had fourteen panels in a fixed 1.5fr/.75fr split — ten tall
|
||||
// ones on the left, four short forms on the right. The right column ran out a
|
||||
// quarter of the way down and you scrolled past dead space for the rest.
|
||||
// Grouping them into tabs lets every panel use the full width.
|
||||
(function () {
|
||||
'use strict';
|
||||
var KEY = 'rmc.admin.tab';
|
||||
|
||||
function panes() { return [].slice.call(document.querySelectorAll('.tabpane')); }
|
||||
function tabs() { return [].slice.call(document.querySelectorAll('#adminTabs .tab')); }
|
||||
|
||||
function show(key) {
|
||||
var found = false;
|
||||
panes().forEach(function (p) {
|
||||
var on = p.getAttribute('data-pane') === key;
|
||||
p.classList.toggle('on', on);
|
||||
if (on) found = true;
|
||||
});
|
||||
if (!found) return false;
|
||||
tabs().forEach(function (t) {
|
||||
var on = t.getAttribute('data-tab') === key;
|
||||
t.classList.toggle('on', on);
|
||||
t.setAttribute('aria-selected', on ? 'true' : 'false');
|
||||
});
|
||||
try { localStorage.setItem(KEY, key); } catch (e) {}
|
||||
return true;
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var bar = document.getElementById('adminTabs');
|
||||
if (!bar) return;
|
||||
|
||||
bar.addEventListener('click', function (e) {
|
||||
var t = e.target.closest('.tab');
|
||||
if (t) show(t.getAttribute('data-tab'));
|
||||
});
|
||||
|
||||
// Left/right arrows move between tabs, as a tablist should.
|
||||
bar.addEventListener('keydown', function (e) {
|
||||
if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;
|
||||
var all = tabs();
|
||||
var i = all.indexOf(document.activeElement);
|
||||
if (i < 0) return;
|
||||
var next = all[(i + (e.key === 'ArrowRight' ? 1 : all.length - 1)) % all.length];
|
||||
next.focus();
|
||||
show(next.getAttribute('data-tab'));
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// Come back to whichever tab was last open.
|
||||
var saved = null;
|
||||
try { saved = localStorage.getItem(KEY); } catch (e) {}
|
||||
if (!saved || !show(saved)) {
|
||||
var first = tabs()[0];
|
||||
if (first) show(first.getAttribute('data-tab'));
|
||||
}
|
||||
});
|
||||
})();
|
||||
+2
-15
File diff suppressed because one or more lines are too long
@@ -248,3 +248,16 @@ a.brand{text-decoration:none;color:inherit}
|
||||
.pay-diagram{width:100%;min-width:640px;height:auto;display:block}
|
||||
|
||||
img.brand-mark{object-fit:cover;font-size:0}
|
||||
|
||||
/* Admin tabs — replaces the old fixed 1.5fr/.75fr admin-grid, which left the
|
||||
right column empty for most of the page. */
|
||||
.tabs{display:flex;gap:6px;flex-wrap:wrap;border-bottom:1px solid #27445e;margin-bottom:18px}
|
||||
.tab{appearance:none;background:transparent;border:0;border-bottom:2px solid transparent;color:#8da3b5;font:inherit;font-weight:800;font-size:14px;letter-spacing:.4px;padding:12px 17px;cursor:pointer;border-radius:10px 10px 0 0;transition:.15s ease}
|
||||
.tab:hover{color:var(--text);background:rgba(255,255,255,.035)}
|
||||
.tab.on{color:var(--gold);border-bottom-color:var(--gold);background:rgba(243,190,67,.07)}
|
||||
.tab:focus-visible{outline:2px solid var(--teal);outline-offset:-2px}
|
||||
.tabpane{display:none;gap:18px;grid-template-columns:1fr;align-content:start}
|
||||
.tabpane.on{display:grid}
|
||||
.pane-split{display:grid;grid-template-columns:1.6fr .9fr;gap:18px;align-items:start}
|
||||
#grantCard summary::-webkit-details-marker{display:none}
|
||||
@media(max-width:900px){.pane-split{grid-template-columns:1fr}.tab{padding:10px 12px;font-size:13px}}
|
||||
|
||||
Reference in New Issue
Block a user