Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions frontend/src/views/AppShell.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ const BMC = 'https://ko-fi.com/devolabode'

/** Top app bar with logo + nav, global footer. Donate lives in the footer. */
export default function AppShell({ children, route, onNav, authed, user, theme, onToggleTheme }) {
const inApp = route === 'results' || route === 'problem'
// Show New scan when signed in (stable header order), and also on results /
// problem for guests or signed-in users who have not connected storage yet —
// App passes authed={authed && storageReady}, and those routes have no guard.
const showNewScan =
(authed || route === 'results' || route === 'problem') &&
route !== 'signin' &&
route !== 'connect'

const NavLink = ({ to, children }) => (
<button onClick={() => onNav(to)} style={{
Expand Down Expand Up @@ -45,27 +51,27 @@ export default function AppShell({ children, route, onNav, authed, user, theme,
<button onClick={() => onNav('landing')} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 0 }} aria-label="Vizably home">
<Logo size={28} />
</button>
<nav style={{ display: 'flex', alignItems: 'center', gap: 20 }}>
<nav aria-label="Primary" style={{ display: 'flex', alignItems: 'center', gap: 20 }}>
<button onClick={onToggleTheme} aria-label={theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'} title={theme === 'dark' ? 'Light mode' : 'Dark mode'} style={{
width: 34, height: 34, borderRadius: '50%', display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
border: '1px solid var(--border-default)', background: 'var(--surface-card)', color: 'var(--text-body)', cursor: 'pointer',
}}>{Ico(theme === 'dark' ? 'Sun' : 'Moon', 17, 'currentColor')}</button>
{inApp && (
{showNewScan && (
<Button size="sm" variant="secondary" onClick={() => onNav('landing')} iconLeft={Ico('Plus', 16)}>New scan</Button>
)}
{authed ? (
<>
<NavLink to="dashboard">My scans</NavLink>
<button onClick={() => onNav('account')} aria-label="Account settings" style={{
width: 34, height: 34, borderRadius: '50%',
border: route === 'account' ? '2px solid var(--accent)' : '1px solid var(--border-default)',
background: 'var(--accent-subtle)', color: 'var(--accent)', cursor: 'pointer',
font: 'var(--font-sans)', fontWeight: 'var(--weight-bold)', fontSize: 'var(--text-sm)',
}}>{initials}</button>
</>
<NavLink to="dashboard">My scans</NavLink>
) : (
<NavLink to="signin">Sign in</NavLink>
)}
{authed && (
<button onClick={() => onNav('account')} aria-label="Account settings" style={{
width: 34, height: 34, borderRadius: '50%',
border: route === 'account' ? '2px solid var(--accent)' : '1px solid var(--border-default)',
background: 'var(--accent-subtle)', color: 'var(--accent)', cursor: 'pointer',
font: 'var(--font-sans)', fontWeight: 'var(--weight-bold)', fontSize: 'var(--text-sm)',
}}>{initials}</button>
)}
</nav>
</header>

Expand Down