home: last admin + owner — destroy becomes THE button, not a footnote link (#489)
When the space reports this is its only admin key AND this account created it, 'Delete your access' was a permanently-disabled button with a note pointing at a small 'Destroy the space for everyone…' link below it — three competing elements for one possible action. Now that state flips the whole step to the destroy framing: title 'Destroy this space?', one red note naming the space and the consequence, and the destroy action promoted into the primary button slot (same typed-host arming + fresh-passkey ceremony). The other states are unchanged: owner-not-sole-admin keeps the footnote link; sole-admin-not-owner keeps the make-another-admin-first hold.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2 files changed,
+36
−11
home/web/pages/index.html+9 −4home/web/static/home.js+27 −7
diff --git a/home/web/pages/index.html b/home/web/pages/index.html| index 8bbd5f7..6f0d5e4 100644 |
| --- a/home/web/pages/index.html |
| +++ b/home/web/pages/index.html |
| @@ -178,6 +178,9 @@ |
| /* Archive screen. The list is quiet; the permanent delete is deliberately loud. */ |
| #archive { text-align: center; } |
| #destroy-zone { margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--border); } |
| + /* When destroying is the only action (last admin + owner), the zone IS the |
| + primary action — no footnote separator; the button sits where Delete did. */ |
| + #destroy-zone.primary { margin-top: 0; padding-top: 0; border-top: none; } |
| .danger-link { color: var(--danger); font-size: .9rem; } |
| .danger-link:disabled { opacity: .4; cursor: default; text-decoration: none; } |
| .danger-ink { color: var(--danger); } |
| @@ -465,8 +468,8 @@ |
| <p class="create-sub">Checking with the space…</p> |
| </div> |
| <div id="archive-stern" class="hidden"> |
| - <h2 class="create-title danger-ink">Delete your access?</h2> |
| - <p class="create-sub stern-copy">Deleting <b id="stern-name"></b> removes your only |
| + <h2 class="create-title danger-ink" id="stern-title">Delete your access?</h2> |
| + <p class="create-sub stern-copy" id="stern-intro">Deleting <b id="stern-name"></b> removes your only |
| saved way back into <b id="stern-host"></b>. If you're not signed in to it on |
| another device, you'll lose access <b>forever</b> — there will be no way back |
| in. <b>This cannot be undone.</b></p> |
| @@ -477,9 +480,11 @@ |
| spellcheck="false" aria-label="Type the space address to confirm"> |
| <button id="delete-access" type="button" class="btn-danger" disabled>Delete forever</button> |
| <!-- Owner-only, revealed once ownership is confirmed: also destroy the space |
| - itself, for everyone. Gated by the same typed confirmation + a passkey. --> |
| + itself, for everyone. Gated by the same typed confirmation + a passkey. |
| + When the last-admin hold engages too, destroying is the only real action |
| + left, so home.js promotes this from a footnote link to THE button. --> |
| <div id="destroy-zone" class="hidden"> |
| - <p class="create-sub stern-copy">You created this space, so you can also |
| + <p class="create-sub stern-copy" id="destroy-note">You created this space, so you can also |
| <b>destroy it for everyone</b> — every message, photo, and member in it.</p> |
| <button id="destroy-forever" type="button" class="linkish danger-link" disabled>Destroy the space for everyone…</button> |
| </div> |
diff --git a/home/web/static/home.js b/home/web/static/home.js| index e396d33..0a23fc1 100644 |
| --- a/home/web/static/home.js |
| +++ b/home/web/static/home.js |
| @@ -867,19 +867,39 @@ function checkSoleAdmin(s) { |
| // updateSternHold renders what the checks learned: the destroy zone when this |
| // account owns the space, and the last-admin hold — "Delete your access" goes |
| -// (and stays) off, with the note saying why and what to do instead: destroy the |
| -// space below, or hand admin to someone else first. |
| +// (and stays) off. When BOTH hold (last admin of a space this account created), |
| +// destroying is the only real action left, so it isn't offered as a footnote |
| +// link under a dead button: the whole step flips to the destroy framing — |
| +// title, copy, and the destroy button promoted to the primary slot. Rendering |
| +// is declarative from the two flags, so straggling checks re-render cleanly. |
| function updateSternHold() { |
| + const destroyOnly = sternSoleAdmin && sternDestroyable; |
| + $("stern-title").textContent = destroyOnly ? "Destroy this space?" : "Delete your access?"; |
| + $("stern-intro").classList.toggle("hidden", destroyOnly); |
| + $("delete-access").classList.toggle("hidden", destroyOnly); |
| $("destroy-zone").classList.toggle("hidden", !sternDestroyable); |
| + $("destroy-zone").classList.toggle("primary", destroyOnly); |
| + $("destroy-note").classList.toggle("hidden", destroyOnly); |
| + const destroy = $("destroy-forever"); |
| + destroy.className = destroyOnly ? "btn-danger" : "linkish danger-link"; |
| + destroy.textContent = destroyOnly ? "Destroy the space for everyone" : "Destroy the space for everyone…"; |
| const note = $("sole-admin-note"); |
| if (!sternSoleAdmin) { note.classList.add("hidden"); return; } |
| - note.textContent = sternDestroyable |
| - ? "This is the space's only admin key. Deleting just your access would leave " + |
| - "the space running with no admin, forever — to actually shut it down, use " + |
| - "“Destroy the space for everyone” below instead." |
| - : "This is the space's only admin key. Deleting it would leave the space " + |
| + if (destroyOnly) { |
| + const host = Object.assign(document.createElement("b"), { textContent: $("stern-host").textContent }); |
| + const noUndo = Object.assign(document.createElement("b"), { textContent: "This cannot be undone." }); |
| + note.replaceChildren( |
| + "This is the only admin key for ", host, " — deleting just your access would ", |
| + "leave the space running with no admin, forever. You created it, so you can ", |
| + "destroy the space for everyone instead: every message, photo, and member ", |
| + "in it. ", noUndo, |
| + ); |
| + } else { |
| + note.textContent = |
| + "This is the space's only admin key. Deleting it would leave the space " + |
| "running with no admin, forever. Make another member an admin first, then " + |
| "come back to delete your access."; |
| + } |
| note.classList.remove("hidden"); |
| $("delete-access").disabled = true; |
| } |