Consolidate Boundaries + History under the account; sectioned /account

The inline Boundaries/History panels lived on the home page, so opening them while
scrolled left you stranded. Move everything "yours" behind the account icon:

- Home header slims to: Saved (opens a right-side flyout, signed-in) · shield
  (Boundaries indicator — filled when active — linking to the Boundaries section) ·
  avatar. The inline panels + the home "saved" view are gone.
- /account is now a sectioned hub (left sidebar on desktop, top tabs on mobile),
  OPEN TO EVERYONE with each section self-gating: Profile (sign-in), Saved (sign-in),
  History (device/account), Boundaries (device/account), Admin (admins). This keeps
  Boundaries/History usable without an account (they're device-local) while
  consolidating the UI — and every section loads at the top, fixing the scroll bug.
- Lift Calm Filters and History into shared stores (prefs.svelte.js, history.svelte.js)
  so the home feed (applies/records) and the account page (edits/manages) share one
  source of truth. New SavedFlyout component. Card boundary actions only render when a
  handler is provided.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jay
2026-06-04 01:59:53 +00:00
parent d1a4b24627
commit 3924d927aa
10 changed files with 3184 additions and 294 deletions
+26 -23
View File
@@ -1,6 +1,6 @@
<script>
import Avatar from './Avatar.svelte';
let { onBoundaries, onHistory, onaccount, user = null, filtersOn = false } = $props();
let { onSaved, onaccount, user = null, boundariesActive = false } = $props();
</script>
<header class="appbar">
@@ -10,17 +10,19 @@
</a>
<nav class="utils" aria-label="Your controls">
<button class:on={filtersOn} onclick={onBoundaries} title="Your boundaries">
{#if user}
<button class="util" onclick={onSaved} title="Saved articles">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 3h12v18l-6-4-6 4z"
fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" /></svg>
<span>Saved</span>
</button>
{/if}
<a class="util shield" class:on={boundariesActive} href="/account?section=boundaries"
title={boundariesActive ? 'Boundaries are on' : 'Your boundaries'}>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3l7 3v5c0 4.4-3 7.6-7 9-4-1.4-7-4.6-7-9V6l7-3z"
fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" /></svg>
<span>Boundaries</span>
</button>
<button onclick={onHistory} title="What you've seen">
<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8.5" fill="none"
stroke="currentColor" stroke-width="1.8" /><path d="M12 7v5l3.5 2" fill="none"
stroke="currentColor" stroke-width="1.8" stroke-linecap="round" /></svg>
<span>History</span>
</button>
fill={boundariesActive ? 'currentColor' : 'none'} stroke="currentColor" stroke-width="1.8"
stroke-linejoin="round" /></svg>
</a>
{#if user}
<button class="acct" onclick={onaccount} title={user.email} aria-label="Your account">
<Avatar {user} size={30} />
@@ -39,29 +41,30 @@
position: sticky;
top: 0;
z-index: 20;
/* a whisper of warmth under the bar */
box-shadow: 0 1px 0 rgba(40, 38, 28, 0.02);
}
.bar { display: flex; align-items: center; justify-content: space-between; height: 78px; }
.brand { display: inline-flex; align-items: center; }
.logo { height: 54px; width: auto; display: block; }
.utils { display: flex; gap: 6px; }
.utils button {
.utils { display: flex; align-items: center; gap: 4px; }
.utils .util {
display: inline-flex; align-items: center; gap: 7px;
background: none; border: 1px solid transparent; border-radius: 999px;
padding: 7px 13px; color: var(--muted); font-size: 0.86rem; cursor: pointer;
padding: 7px 12px; color: var(--muted); font-size: 0.86rem; cursor: pointer;
transition: background 0.14s ease, color 0.14s ease;
}
.utils button svg { width: 17px; height: 17px; }
.utils button:hover { background: var(--accent-soft); color: var(--accent-deep); }
.utils button.on { color: var(--accent-deep); }
.utils .signin { border-color: var(--line); color: var(--accent-deep); }
.utils .signin:hover { background: var(--accent-soft); }
.acct { padding: 4px; display: inline-flex; }
.utils .util svg { width: 18px; height: 18px; }
.utils .util:hover { background: var(--accent-soft); color: var(--accent-deep); }
.shield.on { color: var(--accent); }
.acct { background: none; border: none; padding: 4px; display: inline-flex; cursor: pointer; }
.signin {
background: none; border: 1px solid var(--line); border-radius: 999px;
padding: 7px 13px; color: var(--accent-deep); font-size: 0.86rem; cursor: pointer;
}
.signin:hover { background: var(--accent-soft); }
/* On phones the utilities live in the bottom tab bar ("You") instead. */
/* On phones the bottom tab bar handles navigation; keep the bar to the logo. */
@media (max-width: 720px) {
.bar { height: 66px; justify-content: center; }
.utils { display: none; }