relay: burger menu for mobile, admin reachable, badge matches header buttons
The relay's nav row used to flatten on mobile by hiding admin / user
identity / compose buttons outright, leaving only "account" + "logout".
Admin was completely unreachable from a phone. Replaces that with a
proper burger menu and exposes every nav target.
* layout.php: new <button id="nav-burger"> with a ph-list icon between
the spacer and #nav-buttons. Inline `style="display:flex"` removed
from #nav-buttons — display is now CSS-driven, so the burger
popover and the desktop row don't fight each other.
* app.js showView(): the mobile-block on `name === 'admin'` is gone.
Burger button visibility is now mirrored against the same
setup/login/change-password gating that hides #nav-buttons. Picking
any view also clears `.menu-open` so the popover collapses behind
the freshly-shown view.
* app.js toggleNavMenu(): exposed on window for the inline onclick.
Document-level click outside closes the menu.
* style.css: default `#nav-buttons:not(.hidden)` becomes flex (same
semantics as the old inline). #nav-burger is `display:none` on
desktop, `inline-flex` on mobile. Mobile media query drops the old
display:none rules for #nav-admin / #view-admin / #nav-compose,
keeps #nav-user hidden (redundant with the menu), and adds a
`.menu-open` rule that turns #nav-buttons into a popover anchored
to the header (position:absolute, right:12px, surface bg, border,
shadow, z-index 50). Buttons inside the popover go full-width
left-aligned. header { position:relative } so the absolute
positioning has an anchor.
* style.css: also #view-admin .section gets a simple display:block
override on mobile so the desktop grid-area layout doesn't break
the page when admin is opened from a phone.
header .user .badge sizing (carried over from the previous turn): the
admin badge in the relay header now matches the .nav-btn box-model
exactly (5px 10px padding, 9px font, 1px border, 3px radius, line-
height:1, pixel font), so it sits flush with the nav buttons instead
of being a tiny pill in the middle of the row.
chore: bump version to 0.9.8
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
923de0cdd6
commit
a67bedc6f2
4 files changed
+76
-12
No files matched your search
+21
-5
@@ -29,10 +29,6 @@ function showView(name) {
|
||||
if (me && me.password_changed === false && !['setup', 'login', 'change-password'].includes(name)) {
|
||||
name = 'change-password';
|
||||
}
|
||||
// Block admin view on mobile — even if someone tries programmatically
|
||||
if (name === 'admin' && window.matchMedia('(max-width: 700px)').matches) {
|
||||
name = 'compose';
|
||||
}
|
||||
['setup', 'login', 'change-password', 'compose', 'account', 'admin'].forEach(v => {
|
||||
$('view-' + v)?.classList.add('hidden');
|
||||
});
|
||||
@@ -40,13 +36,17 @@ function showView(name) {
|
||||
|
||||
if (['compose', 'account', 'admin'].includes(name)) {
|
||||
$('nav-buttons').classList.remove('hidden');
|
||||
$('nav-buttons').style.display = 'flex';
|
||||
$('nav-compose').classList.toggle('active', name === 'compose');
|
||||
$('nav-account').classList.toggle('active', name === 'account');
|
||||
$('nav-admin').classList.toggle('active', name === 'admin');
|
||||
$('nav-burger')?.classList.remove('hidden');
|
||||
// Picking a view also collapses the mobile menu so it doesn't
|
||||
// hover over the freshly-shown view.
|
||||
$('nav-buttons').classList.remove('menu-open');
|
||||
} else {
|
||||
// Setup, login, and forced change-password hide all nav
|
||||
$('nav-buttons').classList.add('hidden');
|
||||
$('nav-burger')?.classList.add('hidden');
|
||||
}
|
||||
|
||||
if (name === 'compose') {
|
||||
@@ -63,6 +63,22 @@ function showView(name) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Burger toggle for the mobile nav. The button is hidden on desktop
|
||||
* via CSS, on mobile it expands #nav-buttons as a dropdown panel
|
||||
* positioned under the header. */
|
||||
function toggleNavMenu() {
|
||||
$('nav-buttons')?.classList.toggle('menu-open');
|
||||
}
|
||||
window.toggleNavMenu = toggleNavMenu;
|
||||
// Tap outside the menu closes it
|
||||
document.addEventListener('click', (e) => {
|
||||
const nav = $('nav-buttons');
|
||||
const burger = $('nav-burger');
|
||||
if (!nav?.classList.contains('menu-open')) return;
|
||||
if (nav.contains(e.target) || burger?.contains(e.target)) return;
|
||||
nav.classList.remove('menu-open');
|
||||
});
|
||||
|
||||
async function doChangePassword() {
|
||||
const current = $('cp-current').value;
|
||||
const newPw = $('cp-new').value;
|
||||
|
||||
+2
-1
@@ -17,7 +17,8 @@ if (!defined('RELAY_BOOTSTRAPPED')) { http_response_code(404); exit; }
|
||||
<h1>hyprcrd relay</h1>
|
||||
<span id="header-status" class="pixel" style="font-size:9px;color:var(--dim);"></span>
|
||||
<span class="spacer"></span>
|
||||
<div id="nav-buttons" class="hidden" style="display:flex;gap:6px;align-items:center;">
|
||||
<button id="nav-burger" class="nav-btn hidden" aria-label="menu" onclick="toggleNavMenu()"><i class="ph ph-list"></i></button>
|
||||
<div id="nav-buttons" class="hidden">
|
||||
<span id="nav-user" class="user"></span>
|
||||
<button id="nav-compose" class="nav-btn active" onclick="showView('compose')"><i class="ph ph-pencil-line"></i> compose</button>
|
||||
<button id="nav-account" class="nav-btn" onclick="showView('account')"><i class="ph ph-user-circle"></i> account</button>
|
||||
|
||||
+52
-5
@@ -37,7 +37,11 @@ header .user {
|
||||
}
|
||||
header .user .badge {
|
||||
background:var(--accent); color:var(--bg);
|
||||
padding:1px 6px; font-size:8px; border-radius:2px;
|
||||
/* Match the .nav-btn box-model exactly so the badge sits flush with
|
||||
the header buttons instead of being a tiny pill in the middle. */
|
||||
padding:5px 10px; font-size:9px;
|
||||
border:1px solid var(--accent); border-radius:3px;
|
||||
line-height:1; font-family:var(--pixel);
|
||||
}
|
||||
header .nav-btn {
|
||||
background:none; border:1px solid var(--border); color:var(--muted);
|
||||
@@ -236,12 +240,55 @@ header h1 + .ph { font-size:12px; }
|
||||
.btn .ph { font-size:12px; vertical-align:-2px; margin-right:2px; }
|
||||
.section h2 .ph, .compose-card h2 .ph { font-size:13px; vertical-align:-2px; }
|
||||
|
||||
/* ── Mobile: hide admin, identity, and the compose nav button ── */
|
||||
/* ── Default nav layout (desktop) ── */
|
||||
#nav-buttons:not(.hidden) {
|
||||
display:flex; gap:6px; align-items:center;
|
||||
}
|
||||
#nav-burger {
|
||||
display:none; /* desktop hides the burger */
|
||||
padding:5px 10px; font-size:11px;
|
||||
}
|
||||
|
||||
/* ── Mobile: collapse nav into a burger menu ── */
|
||||
@media (max-width: 700px) {
|
||||
#nav-admin { display:none !important; }
|
||||
#view-admin { display:none !important; }
|
||||
/* Hide identity tag on mobile — it's redundant with the menu */
|
||||
#nav-user { display:none !important; }
|
||||
#nav-compose { display:none !important; }
|
||||
/* Burger replaces the inline nav row */
|
||||
#nav-burger { display:inline-flex !important; align-items:center; }
|
||||
/* Default-hide the nav row; .menu-open re-shows it as a popover */
|
||||
#nav-buttons:not(.hidden) { display:none; }
|
||||
#nav-buttons.menu-open {
|
||||
display:flex !important;
|
||||
flex-direction:column;
|
||||
align-items:stretch;
|
||||
position:absolute;
|
||||
top:100%;
|
||||
right:12px;
|
||||
margin-top:6px;
|
||||
background:var(--surface);
|
||||
border:1px solid var(--border);
|
||||
border-radius:4px;
|
||||
box-shadow:0 8px 24px rgba(0,0,0,0.4);
|
||||
padding:6px;
|
||||
gap:4px;
|
||||
min-width:160px;
|
||||
z-index:50;
|
||||
}
|
||||
#nav-buttons.menu-open .nav-btn {
|
||||
text-align:left;
|
||||
width:100%;
|
||||
}
|
||||
/* Anchor the popover to the header row */
|
||||
header { position:relative; }
|
||||
|
||||
/* Admin view on mobile: stack the two columns. The desktop layout
|
||||
has its own grid; here we just let the section scroll naturally. */
|
||||
#view-admin .section {
|
||||
display:block !important;
|
||||
padding:14px 12px;
|
||||
}
|
||||
#view-admin .section h2 { margin-bottom:10px; }
|
||||
#view-admin .section .create-user-form { margin-top:14px; }
|
||||
}
|
||||
|
||||
/* ── Desktop layout ── */
|
||||
|
||||
Reference in new issue
Block a user