15728c3bcb
- Capture the Google profile picture (picture claim) into users.avatar_url; an Avatar component shows it, falling back to the initial. Used in the desktop header and the mobile "You" tab (which now shows the user when signed in). - Move account/settings to its own route /account (robust + scrolls to top), reached by the desktop avatar and the mobile You tab; drop the inline "You" sheet. AccountPanel gains a Sign out action; the page links to Saved/History/ Boundaries via home intent params (?view= / ?open=). - db: users.avatar_url (schema + idempotent migration). 118 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
71 lines
2.7 KiB
Svelte
71 lines
2.7 KiB
Svelte
<script>
|
|
import Avatar from './Avatar.svelte';
|
|
let { onBoundaries, onHistory, onaccount, user = null, filtersOn = false } = $props();
|
|
</script>
|
|
|
|
<header class="appbar">
|
|
<div class="container bar">
|
|
<a class="brand" href="/" aria-label="Upbeat Bytes — home">
|
|
<img class="logo" src="/logo.svg" alt="Upbeat Bytes" width="586" height="196" />
|
|
</a>
|
|
|
|
<nav class="utils" aria-label="Your controls">
|
|
<button class:on={filtersOn} onclick={onBoundaries} title="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>
|
|
{#if user}
|
|
<button class="acct" onclick={onaccount} title={user.email} aria-label="Your account">
|
|
<Avatar {user} size={30} />
|
|
</button>
|
|
{:else}
|
|
<button class="signin" onclick={onaccount}>Sign in</button>
|
|
{/if}
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<style>
|
|
.appbar {
|
|
background: var(--surface);
|
|
border-bottom: 1px solid var(--line);
|
|
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 {
|
|
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;
|
|
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; }
|
|
|
|
/* On phones the utilities live in the bottom tab bar ("You") instead. */
|
|
@media (max-width: 720px) {
|
|
.bar { height: 66px; justify-content: center; }
|
|
.utils { display: none; }
|
|
.logo { height: 46px; }
|
|
}
|
|
</style>
|