bzl

self-hosted ephemeral community engine
Log | Files | Refs | README | LICENSE

commit 0c8eaff808437374fb56fc7e4236fa300b3539a6
parent 1685bc8eb6148d3a45b5f00dd11beb8e9b2d352a
Author: SageAzakaela <106701693+SageAzakaela@users.noreply.github.com>
Date:   Mon, 23 Feb 2026 00:20:09 -0700

second onboarding pass

Diffstat:
Mpublic/app.js | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpublic/index.html | 3++-
Mpublic/styles.css | 19+++++++++++++++++++
3 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/public/app.js b/public/app.js @@ -118,6 +118,7 @@ const mobileSortCycleBtn = document.getElementById("mobileSortCycle"); const clearFilterBtn = document.getElementById("clearFilter"); const feedEl = document.getElementById("feed"); const hiveTabsEl = document.getElementById("hiveTabs"); +const onboardingGateHintEl = document.getElementById("onboardingGateHint"); const onboardingPanelEl = document.getElementById("onboardingPanel"); const onboardingPanelBodyEl = document.getElementById("onboardingPanelBody"); const onboardingPanelAcceptBtn = document.getElementById("onboardingPanelAccept"); @@ -6680,6 +6681,57 @@ function onboardingNeedsAcceptanceNow() { return Boolean(onboardingState.needsAcceptance || Number(onboardingState.acceptedRulesVersion || 0) < Number(onboardingState.rulesVersion || 1)); } +function onboardingBlocksReadingNow() { + return Boolean(loggedInUser && onboardingNeedsAcceptanceNow() && onboardingState.blockReadUntilAccepted); +} + +function openOnboardingView() { + onboardingViewerTab = "about"; + renderOnboardingPanel(); + if (isMobileScreenMode()) { + const layout = loadMobileLayout(); + layout.active = "onboarding"; + saveMobileLayout(layout); + setMobileScreen("onboarding"); + renderMobileNav(); + return; + } + if (rackLayoutEnabled) { + try { + if ( + layoutPresetEl instanceof HTMLSelectElement && + Array.from(layoutPresetEl.options || []).some((opt) => String(opt.value || "") === "onboardingDefault") + ) { + if (layoutPresetEl.value !== "onboardingDefault") layoutPresetEl.value = "onboardingDefault"; + applyPreset("onboardingDefault"); + } + restorePanelToWorkspaceSlot("onboarding", "workspaceLeftSlot"); + restorePanelToWorkspaceSlot("hives", "workspaceRightSlot"); + } catch { + // ignore layout failures + } + } + try { + onboardingPanelEl?.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" }); + } catch { + // ignore + } +} + +function renderOnboardingGateHint() { + if (!(onboardingGateHintEl instanceof HTMLElement)) return; + const show = onboardingBlocksReadingNow(); + onboardingGateHintEl.classList.toggle("hidden", !show); + if (!show) { + onboardingGateHintEl.innerHTML = ""; + return; + } + onboardingGateHintEl.innerHTML = ` + <div class="onboardingGateText">This instance requires that you read and accept its guidelines before you can view posts.</div> + <button type="button" class="ghost smallBtn" data-onboarding-open="1">Go to Onboarding</button> + `; +} + function onboardingSeverityLabel(severity) { const s = String(severity || "").toLowerCase(); if (s === "critical") return "Critical"; @@ -6907,6 +6959,7 @@ function setAuthUi() { codeRow.classList.toggle("hidden", !registrationEnabled); registerBtn.classList.toggle("hidden", !(registrationEnabled || canRegisterFirstUser)); if (appRoot) appRoot.classList.toggle("authLockedWorkspace", !loggedInUser); + renderOnboardingGateHint(); renderOnboardingCard(); renderModPanel(); if (tourBtn instanceof HTMLButtonElement) { @@ -10888,6 +10941,12 @@ feedEl.addEventListener("click", (e) => { } }); +onboardingGateHintEl?.addEventListener("click", (e) => { + const btn = e.target?.closest?.("button[data-onboarding-open]"); + if (!btn) return; + openOnboardingView(); +}); + window.addEventListener("keydown", (e) => { if (e.key !== "Escape") return; if (!openPostMenuId) return; diff --git a/public/index.html b/public/index.html @@ -4,7 +4,7 @@ <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Bzl - Hives</title> - <link rel="stylesheet" href="/styles.css?v=132" /> + <link rel="stylesheet" href="/styles.css?v=133" /> </head> <body> <div class="app"> @@ -218,6 +218,7 @@ </div> </div> <div class="uiHint">Use filters to narrow posts, then tap <b>Chat</b> on a hive card. Cards now show latest chat/typing. Shortcut: <b>-</b>/<b>=</b> cycles collections/views.</div> + <div id="onboardingGateHint" class="onboardingGateHint hidden"></div> <div class="hiveTabs" id="hiveTabs"> <button type="button" data-hiveview="all" class="primary">All</button> <button type="button" data-hiveview="starred" class="ghost">Starred</button> diff --git a/public/styles.css b/public/styles.css @@ -3841,6 +3841,25 @@ button:disabled { pointer-events: none; } +.onboardingGateHint { + margin-top: 8px; + margin-bottom: 8px; + border-radius: 12px; + border: 1px solid color-mix(in oklab, var(--bad) 55%, var(--line) 45%); + background: linear-gradient(180deg, rgba(255, 77, 138, 0.16), rgba(255, 77, 138, 0.07)); + padding: 10px 12px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; +} + +.onboardingGateText { + color: color-mix(in oklab, var(--text) 92%, white 8%); + font-size: 13px; + line-height: 1.35; +} + .guidedTourCard { position: absolute; left: 50%;