Files
upbeatBytes/frontend/src/lib/components/Header.svelte
T
thejayman77 667b1a82c3 brand: standardize "Upbeat Bytes" → "upbeatBytes" everywhere
Per the logo + brand: the name is upbeatBytes (camelCase). Swept all user-facing
strings — titles/og:site_name/og:title, logo alt text, share pages (share.py),
emails (email_send), classifier prompt (llm), digest/unsubscribe (api), PWA
manifest, game share text, sign-in, the SPA shell + patch-static-heads (play
title) — plus README/publish.sh and the email test fixture. (SMTP From env was
already upbeatBytes.) Domains (upbeatbytes.com) unchanged. 425 BE + 36 FE green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 20:01:20 -04:00

85 lines
3.9 KiB
Svelte

<script>
import Avatar from './Avatar.svelte';
import { openFeedback } from '$lib/feedback.svelte.js';
let { onSaved, onaccount, user = null, boundariesActive = false } = $props();
</script>
<header class="appbar">
<div class="container bar">
<a class="brand" href="/" aria-label="upbeatBytes — home">
<img class="logo" src="/logo.svg" alt="upbeatBytes" width="586" height="196" />
</a>
<nav class="utils" aria-label="Your controls">
<a class="util desk" href="/play" title="Play — daily puzzles">
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="4" width="7" height="7" rx="2" fill="none" stroke="currentColor" stroke-width="1.8"/><rect x="13" y="4" width="7" height="7" rx="2" fill="none" stroke="currentColor" stroke-width="1.8"/><rect x="4" y="13" width="7" height="7" rx="2" fill="none" stroke="currentColor" stroke-width="1.8"/><rect x="13" y="13" width="7" height="7" rx="2" fill="none" stroke="currentColor" stroke-width="1.8"/></svg>
<span>Play</span>
</a>
{#if user}
<button class="util desk" 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 desk" 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={boundariesActive ? 'currentColor' : 'none'} stroke="currentColor" stroke-width="1.8"
stroke-linejoin="round" /></svg>
</a>
<!-- Feedback bubble: the one control kept on the mobile bar too. -->
<button class="util" onclick={openFeedback} title="Share feedback" aria-label="Share feedback">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h16v11H8l-4 3z"
fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" /></svg>
</button>
{#if user}
<button class="acct desk" onclick={onaccount} title={user.email} aria-label="Your account">
<Avatar {user} size={30} />
</button>
{:else}
<button class="signin desk" 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;
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; 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 12px; color: var(--muted); font-size: 0.86rem; cursor: pointer;
transition: background 0.14s ease, color 0.14s ease;
}
.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 bottom tab bar handles navigation; the top bar keeps just the
logo (left) and the feedback bubble (right). Other utils move to bottom nav. */
@media (max-width: 720px) {
.bar { height: 66px; }
.utils .desk { display: none; }
.logo { height: 46px; }
}
</style>