zebra-spaces: room list — handles don't wrap, full pubkey on its own row(s)

Two-row (sometimes three-row) grid per member using grid-template-areas:
- row 1: badge | handle | mic | meter
- row 2: full 64-char pubkey, monospace, word-break:break-all, wraps as
  many lines as needed (rather than the previous shortHex truncation)
- row 3: mod-action buttons when present

Handle gets white-space:nowrap + ellipsis so a long handle ('bluediamond')
no longer fragments mid-word ('bluediamo nd') across grid lines. Pubkey
column also returns on mobile (was display:none under 500px); the new
layout fits naturally on narrow screens.
This commit is contained in:
Russell Ballestrini 2026-06-02 16:02:39 -04:00
parent 3041a1391a
commit f45e9563aa
No known key found for this signature in database

View file

@ -445,14 +445,26 @@
.note { font-size: 0.75rem; color: #555; line-height: 1.5; }
.meter { height: 8px; border: 1px solid #000; background: #fff; position: relative; overflow: hidden; }
.meter-fill { height: 100%; background: #000; width: 0%; transition: width 0.06s linear; }
/* member rows: badge | handle | pubkey short | mic | meter — mod actions
* wrap to a 2nd row underneath, indented under the handle */
/* member rows: two-row grid per member — handles stay on one line,
* full pubkey gets its own row (wraps across as many lines as it
* needs). Mod buttons take a third row when present. Never truncate
* the pubkey, never wrap a handle mid-word. */
.member {
display: grid;
grid-template-columns: 5.5rem 1fr 4rem 1.4rem 1fr;
align-items: center; gap: 0.55rem; padding: 0.35rem 0;
grid-template-columns: 5.5rem minmax(0, 1fr) 1.4rem 5rem;
grid-template-areas:
"badge handle mic meter"
"badge pub pub pub"
"badge acts acts acts";
align-items: center; gap: 0.35rem 0.55rem; padding: 0.35rem 0;
border-bottom: 1px dotted #ccc; font-size: 0.85rem;
}
.member > .badge { grid-area: badge; align-self: start; }
.member > .handle { grid-area: handle; }
.member > .pub-short { grid-area: pub; }
.member > .mic { grid-area: mic; }
.member > .meter { grid-area: meter; }
.member > .mod-actions { grid-area: acts; }
.member:last-child { border-bottom: none; }
.badge {
font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;
@ -462,18 +474,22 @@
.badge.cohost { background: #444; color: #fff; }
.badge.speaker { background: #fff; color: #000; }
.badge.listener{ background: #fff; color: #888; border-color: #888; }
.handle { font-weight: bold; word-break: break-all; }
/* handle gets its own row — never wrap, scroll if absurdly long */
.handle { font-weight: bold; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.handle .me { color: #060; font-weight: normal; font-size: 0.7rem; margin-left: 0.3rem; }
.pub-short { font-size: 0.7rem; color: #888; }
/* full pubkey, monospace, wraps onto as many lines as it needs */
.pub-short {
font-size: 0.7rem; color: #888;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
word-break: break-all; line-height: 1.3;
}
.raised { color: #b00; font-weight: bold; }
.mic { width: 18px; height: 18px; }
.mic svg { width: 18px; height: 18px; display: block; }
.mod-actions {
display: grid; grid-auto-flow: column; grid-auto-columns: max-content;
gap: 0.3rem;
grid-column: 1 / -1; /* second row, full width */
justify-content: start;
padding-left: 6.05rem; /* line up under the handle (badge col + gap) */
margin-top: 0.2rem;
}
.mod-actions:empty { display: none; } /* no row gap when nothing to do */
@ -513,9 +529,12 @@
.vault-panel { border: 1px dashed #000; padding: 0.7rem; margin-top: 0.5rem; }
.hidden { display: none !important; }
@media (max-width: 500px) {
.member { grid-template-columns: 5rem 1fr 1.4rem; }
.member .pub-short, .member .meter { display: none; }
.mod-actions { padding-left: 5.55rem; }
/* same template-areas layout, tighter columns. pubkey still
* present on its own row (fox: don't truncate keys). meter row
* trims to the right edge of the visible width. */
.member {
grid-template-columns: 4.5rem minmax(0, 1fr) 1.4rem 3rem;
}
}
</style>
<script>
@ -3150,7 +3169,7 @@ function renderRoom(){
const handle = document.createElement('span'); handle.className = 'handle';
handle.textContent = m.handle;
if (m.uuid === myUUID){ const me=document.createElement('span'); me.className='me'; me.textContent='(you)'; handle.appendChild(me); }
const pub = document.createElement('span'); pub.className = 'pub-short'; pub.title = m.pubkey; pub.textContent = shortHex(hex(unb64(m.pubkey)));
const pub = document.createElement('span'); pub.className = 'pub-short'; pub.title = m.pubkey; pub.textContent = hex(unb64(m.pubkey));
const micEl = document.createElement('span'); micEl.className = 'mic';
if (canSpeak(m.role)){
micEl.innerHTML = m.muted ? MIC_OFF : MIC_ON;
@ -3603,8 +3622,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> &nbsp;·&nbsp; built <span class="stamp-date">2026-06-02</span><br>
md5 <span class="stamp-md5">9874964f15f679f199a10f6b652d6ca4</span><br>
sha256 <span class="stamp-sha">322d72414d2e6cb89de6e8ee961f312fffdea9e539d77650efa6d9ec1844be77</span><br>
md5 <span class="stamp-md5">10e2788f6e51aa1cef858547583e2698</span><br>
sha256 <span class="stamp-sha">619494744ad0f8db36a2b9d127ccfe443972b3602c5a3a689c99d208d626840f</span><br>
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
</footer>