A calm place to write long-form, and publish it to the open social web. skypress.blog/
0

Configure Feed

Select the types of activity you want to include in your feed.

Hide editor/dashboard cross-link in header when signed out

The contextual nav link (Publications on /editor, Write on /dashboard)
rendered whenever auth was not loading, so signed-out visitors saw a
link into editor-only routes they cannot use. Gate it on signed-in
state instead, matching the identity block and sign-out button.

Adds AppBar render-branch tests covering the link's visibility across
loading / signed-out / signed-in states on both page contexts.

+75 -3
+71
src/components/AppBar.test.tsx
··· 1 + import { describe, it, expect } from 'vitest'; 2 + import { createElement } from 'react'; 3 + import { renderToStaticMarkup } from 'react-dom/server'; 4 + import AppBar from './AppBar'; 5 + import { AuthContext, type AuthContextValue } from '../lib/auth/AuthProvider'; 6 + import type { AppBarContext } from '../lib/auth/nav'; 7 + 8 + /** Render the AppBar under a hand-rolled auth context (bypasses real OAuth). */ 9 + function renderBar( current: AppBarContext, auth: Partial< AuthContextValue > ): string { 10 + const value: AuthContextValue = { 11 + status: 'signed-out', 12 + agent: null, 13 + did: null, 14 + handle: null, 15 + displayName: null, 16 + avatar: null, 17 + pdsUrl: null, 18 + error: null, 19 + signIn: async () => {}, 20 + signOut: async () => {}, 21 + ...auth, 22 + }; 23 + return renderToStaticMarkup( 24 + createElement( AuthContext.Provider, { value }, createElement( AppBar, { current } ) ) 25 + ); 26 + } 27 + 28 + describe( 'AppBar contextual nav visibility', () => { 29 + it( 'hides the Publications link on the editor when signed out', () => { 30 + const markup = renderBar( 'editor', { status: 'signed-out' } ); 31 + expect( markup ).not.toContain( 'Publications' ); 32 + expect( markup ).not.toContain( 'href="/dashboard"' ); 33 + } ); 34 + 35 + it( 'hides the Write link on the dashboard when signed out', () => { 36 + const markup = renderBar( 'dashboard', { status: 'signed-out' } ); 37 + expect( markup ).not.toContain( 'Write' ); 38 + expect( markup ).not.toContain( 'href="/editor"' ); 39 + } ); 40 + 41 + it( 'hides the contextual nav while auth is still loading', () => { 42 + const markup = renderBar( 'editor', { status: 'loading' } ); 43 + expect( markup ).not.toContain( 'Publications' ); 44 + } ); 45 + 46 + it( 'shows the Publications link on the editor when signed in', () => { 47 + const markup = renderBar( 'editor', { 48 + status: 'signed-in', 49 + agent: {} as never, 50 + did: 'did:plc:writer', 51 + handle: 'writer.test', 52 + } ); 53 + expect( markup ).toContain( 'Publications' ); 54 + expect( markup ).toContain( 'href="/dashboard"' ); 55 + } ); 56 + 57 + it( 'shows the Write link on the dashboard when signed in', () => { 58 + const markup = renderBar( 'dashboard', { 59 + status: 'signed-in', 60 + agent: {} as never, 61 + did: 'did:plc:writer', 62 + handle: 'writer.test', 63 + } ); 64 + expect( markup ).toContain( 'Write' ); 65 + expect( markup ).toContain( 'href="/editor"' ); 66 + } ); 67 + 68 + it( 'always shows the SkyPress home link, regardless of auth state', () => { 69 + expect( renderBar( 'editor', { status: 'signed-out' } ) ).toContain( 'SkyPress home' ); 70 + } ); 71 + } );
+4 -3
src/components/AppBar.tsx
··· 44 44 /** 45 45 * The shared top bar for the editor + dashboard islands. Logo on the left; 46 46 * contextual nav + account + sign-out on the right. Rendered inside AuthProvider 47 - * in every auth state: logo-only while loading, + nav when signed out, + account 48 - * and sign-out when signed in. 47 + * in every auth state: logo-only while loading or signed out, + contextual nav, 48 + * account, and sign-out once signed in. The cross-link to Publications / Write is 49 + * gated on auth so signed-out visitors aren't pointed at editor-only routes. 49 50 */ 50 51 export default function AppBar( { current }: { current: AppBarContext } ) { 51 52 const { status, handle, displayName, avatar, did, signOut } = useAuth(); ··· 67 68 68 69 <span className="app-bar__spacer" /> 69 70 70 - { status !== 'loading' && ( 71 + { signedIn && ( 71 72 <a className="app-bar__nav" href={ nav.href }> 72 73 <NavIcon name={ nav.icon } /> 73 74 { nav.label }